6

我不太确定我的代码或结构出了什么问题。我想使用 AsyncTask 下载图像并同时显示进度条。但我尝试了几种不同的方法。它仍然失败,不知道有什么问题。我的结构流程是

ContentID 是一个字符串数组,用于存储图像的内容 ID。

主要问题:它设法从url下载图像并存储到手机中,但下载的图像都是同一个图像。它应该是不同的图像,这不是我所期望的。

次要问题:应用程序下载图像时弹出进度条,但进度条没有更新它的进度。它只是保持 0% 并在下载完成后关闭。

我想知道是什么导致了我提到的主要和次要问题。如果您知道我的代码有什么问题,请发表评论或回答。任何帮助将不胜感激。

if(isSyncSuccess){

     SetConstant.IMAGE_EXIST = 1;
     pDialog = new ProgressDialog(GalleryScreen.this);
     pDialog.setMessage("Downloading file. Please wait...");
     pDialog.setIndeterminate(false);
     pDialog.setProgress(0);
     pDialog.setMax(contentId.length);
     pDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
     pDialog.setCancelable(true);


     if (contentId.length>0){
     Log.i(TAG, "contentid.length:" +contentId.length);
         for (int i=0;i<contentId.length;i++){
             if(helper.databaseChecking(useremail, contentId[i])){
                 contentdownload = i;
                 SetConstant.CONTENT_ID = contentId[i]; 

                 String URL = SetConstant.URL_DOWNLOAD_CONTENT+contentId[i];

                 DownloadFile downloadFile = new DownloadFile();
                 downloadFile.execute(URL);


                 }



    private class DownloadFile extends AsyncTask<String, Integer, String>{
    @Override
    protected String doInBackground(String... sUrl){
                Bitmap bm;
                InputStream in;

        try{

            in = new java.net.URL(sUrl[0]).openStream();
            bm = BitmapFactory.decodeStream(new PatchInputStream(in));
            File storage = new File(Environment.getExternalStorageDirectory() + File.separator + "/Image/");
            Log.i(TAG,"storage:" +storage);
            Log.i(TAG,"storage:" +storage.getAbsolutePath());
            if(!storage.exists()){
                storage.mkdirs();

            }
                String FileName = "/"+SetConstant.CONTENT_ID+".jpg"; 
                FileOutputStream fos = new FileOutputStream(storage + FileName);
                bm.compress(Bitmap.CompressFormat.JPEG, 85, fos);

                String filepath = storage + FileName;
                File filecheck = new File (filepath);
                long fileSize = filecheck.length();
                fos.flush();
                fos.close();

                Log.i(TAG, "bm:" +bm);
                Log.i(TAG, "fos:" +fos);
                Log.i(TAG, "filesize:" +fileSize);
                Log.i(TAG, "filepath:" +filepath);


        }
        catch(IOException e1){
                e1.printStackTrace();
                }   

        return null;
    }

    @Override
    protected void onPreExecute(){
        super.onPreExecute();
        pDialog.show();
    }

    @Override
    protected void onProgressUpdate(Integer... progress){
        super.onProgressUpdate(progress);
        pDialog.setProgress(progress[0]);
    }

    protected void onPostExecute(String result){
        super.onPostExecute(result);
        pDialog.dismiss();
    }
}

编辑

现在该应用程序能够根据进度条下载图像了!但是我遇到的另一个问题是当应用程序无法完成下载时如何返回错误消息。目前,当应用程序下载失败时,它会崩溃。我相信我不应该在 doInBackground 里面运行它。但是我还能在哪里进行检查?知道如何作为错误消息返回并请求用户重试而不是使应用程序崩溃吗?

4

4 回答 4

5

onProgressUpdatedoInBackGround(...). 请注意,运行多个实例AsyncTask是一个坏主意。这是我的建议:

if(isSyncSuccess){
    SetConstant.IMAGE_EXIST=1;
    pDialog=new ProgressDialog(GalleryScreen.this);
    pDialog.setMessage("Downloading file. Please wait...");
    pDialog.setIndeterminate(false);
    pDialog.setProgress(0);
    pDialog.setMax(contentId.length);
    pDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
    pDialog.setCancelable(true);

    new DownloadFile().execute();
}

private class DownloadFiles extends AsyncTask<String, Integer, String> {
    @Override
    protected String doInBackground(String... sUrl) {
        Bitmap bm;
        InputStream in;

        if (contentId.length > 0) {
            for (int i = 0; i < contentId.length; i++) {
                if (helper.databaseChecking(useremail, contentId[i])) {
                    contentdownload = i;
                    SetConstant.CONTENT_ID = contentId[i];

                    String URL = SetConstant.URL_DOWNLOAD_CONTENT + contentId[i];
                    //YOUR INTRESTING LOOP HERE.
                    publishProgress(30);
                    //SOME INTRESTING NUMBER FOR PROGRESS UPDATE
                }
            }

            try {
                in = new java.net.URL(sUrl[0]).openStream();
                bm = BitmapFactory.decodeStream(new PatchInputStream(in));
                File storage = new File(Environment.getExternalStorageDirectory() + File.separator + "/Image/");
                Log.i(TAG, "storage:" + storage);
                Log.i(TAG, "storage:" + storage.getAbsolutePath());
                if (!storage.exists()) {
                    storage.mkdirs();

                }
                String FileName = "/" + SetConstant.CONTENT_ID + ".jpg";
                FileOutputStream fos = new FileOutputStream(storage + FileName);
                bm.compress(Bitmap.CompressFormat.JPEG, 85, fos);

                String filepath = storage + FileName;
                File filecheck = new File(filepath);
                long fileSize = filecheck.length();
                fos.flush();
                fos.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }

            return null;
        }

        @Override
        protected void onPreExecute () {
            super.onPreExecute();
            pDialog.show();
        }

        @Override
        protected void onProgressUpdate (Integer...progress){
            super.onProgressUpdate(progress);
            pDialog.setProgress(progress[0]);
        }

        protected void onPostExecute (String result){
            super.onPostExecute(result);
            pDialog.dismiss();
        }
    }
}

当然,此代码不会运行,您需要修复范围。但我想建议的是,您的循环应该在 中,在这种情况下,您应该在给定时间doInBackGround(...)只有 1 个实例,然后调用.AsyncTaskonProgressUpdate()

于 2012-12-21T02:46:25.777 回答
2

在以下行中:

SetConstant.CONTENT_ID = contentId[i];

您将全局变量设置为一个值,然后基于该相同值创建一个字符串 url 并将其传递给 AsyncTask。执行,然后当它完成下载时,它会创建一个文件,其名称基于全局变量 SetConstant.CONTENT_ID。

换句话说,您正在另一个线程中使用一个全局变量,其值正在由主线程更改。不要这样做,因为不同的线程在不同的时间更新,你会遇到各种奇怪的问题。将输出文件的值或名称传递给 AsyncTask。您可以在 DownloadFile 的构造函数中执行此操作,并将值存储在字段中。

如果要更新进度条,则必须更新其值;它不会自行更新。在任务期间(在 doInBackground 中)调用 AsyncTask.publishProgress 并实现 onProgressUpdate 以更新进度对话框。

[编辑:在 UI 线程中确实调用了 onProgressUpdate。]

于 2012-12-21T02:48:09.103 回答
2

主要问题:

SetConstant.CONTENT_ID = contentId[i]; 
String URL = SetConstant.URL_DOWNLOAD_CONTENT+contentId[i];

在这里,你遇到了麻烦。正如@Sofi Software LLC 的回答,您正在另一个线程中使用一个全局变量,其值正在由主线程更改。

次要问题:

  • 如果要更新进度条,则必须更新其值;
    它不会自行更新。

您确实需要在 AsyncTask 中下载图像(从 URL 下载)。有效地实现你的功能,你需要做

  • 创建 AsyncTask 来下载你的图像(在 doInBackground() 中实现下载),还有一个布尔值(比如 isImageDownloaded)来跟踪图像是否在 postExecute() 中成功下载。
  • 在开始下载之前不要忘记显示您的进度条
  • 执行您的 AsyncTask 以启动下载
  • 创建 android.os.CountDownTimer 的扩展以倒计时最短时间
  • 在 onFinish() 方法上检查您跟踪的布尔值,如果它是假的,那么您取消 AsyncTask 并抛出您想要的 toast/dialog
  • 运行多个 AsyncTask 实例不是一个好主意,所以一个接一个。您可以使用 executeOnExecutor() 在 Executor 上执行 AsyncTask。要确保线程以串行方式运行,请使用:SERIAL_EXECUTOR。

以下资源可能对您有所帮助#

如果您需要下载图像,请显示进度条并在图像视图中加载

如果您需要使用 AsyncTask 下载多个文件(此处为图像)

编辑:

来自http://developer.aiwgame.com/imageview-show-image-from-url-on-android-4-0.html

new DownloadImageTask((ImageView) findViewById(R.id.imageView1))
            .execute("http://java.sogeti.nl/JavaBlog/wp-content/uploads/2009/04/android_icon_256.png"); }

public void onClick(View v) {
    startActivity(new Intent(this, IndexActivity.class));
    finish();

}

private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
    ImageView bmImage;

    public DownloadImageTask(ImageView bmImage) {
        this.bmImage = bmImage;
    }

    protected Bitmap doInBackground(String... urls) {
        String urldisplay = urls[0];
        Bitmap mIcon11 = null;
        try {
            InputStream in = new java.net.URL(urldisplay).openStream();
            mIcon11 = BitmapFactory.decodeStream(in);
        } catch (Exception e) {
            Log.e("Error", e.getMessage());
            e.printStackTrace();
        }
        return mIcon11;
    }

    protected void onPostExecute(Bitmap result) {
        bmImage.setImageBitmap(result);
    } }

Android ImageView 和 Progressbar 实现中的图像下载

 // note that you could also use other timer related class in Android aside from this CountDownTimer, I prefer this class because I could do something on every interval basis
            // tick every 10 secs (or what you think is necessary)
            CountDownTimer timer = new CountDownTimer(30000, 10000) {

                @Override
                public void onFinish() {
                    // check the boolean, if it is false, throw toast/dialog
                }

                @Override
                public void onTick(long millisUntilFinished) {
                    // you could alternatively update anything you want every tick of the interval that you specified
                }

            };

            timer.start()
于 2012-12-21T05:43:31.460 回答
0

首先创建一个单独的类,允许您访问图像地址

如下所示:

公共类 ImageDownloader 扩展 AsyncTask {

    @Override
    protected Bitmap doInBackground(String... urls) {

        try {

            URL url = new URL(urls[0]);

            HttpURLConnection connection = (HttpURLConnection) url.openConnection();

            connection.connect();

            InputStream inputStream = connection.getInputStream();

            Bitmap myBitmap = BitmapFactory.decodeStream(inputStream);

            return myBitmap;

        } catch (Exception e) {

            e.printStackTrace();

        }

        return null;
    }
}

然后通过创建一个对象来访问该类(通过按钮调用的方法)并执行 Bitmap 任务,如下所示:

公共类 MainActivity 扩展 Activity {

ImageView downloadedImg;

public void downloadImage(View view) {

    ImageDownloader task = new ImageDownloader();
    Bitmap myImage;

    try {
        myImage = task.execute("YOUR IMAGE ADDRESS ........").get();

        downloadedImg.setImageBitmap(myImage);

    } catch (Exception e) {

        e.printStackTrace();
    }

}  

不要忘记: 1 - 在 onCreat 方法中定义 imageView ==> deletedImg = (ImageView) findViewById(R.id.imageView); 2 - 通过用户界面中的按钮链接您创建的方法 ==> (public void downloadImage(View view){}) 3 - 在清单文件中请求权限

于 2018-05-21T17:32:57.077 回答