如何停止执行直到所有异步任务在android中完成执行?

时间:2016-09-02 09:13:01

标签: java android multithreading asynchronous android-asynctask

我在启动画面中的for循环中运行了多个asynctask。我希望应用程序停止执行,直到所有的asynctasks都完成。我想用异步任务和任务完成的总数来更新UI线程。如果有3个任务且1个完成,我想显示1 / 3完成。 这是循环的代码: -

 String[] images = Parse_imgJSON.image;
        for (int i = 0; i < images.length; i++) {
            Log.d("Image ", images[i]);
            download_img(images[i]);
        }

download_img()代码: -

public void download_img(String img_url) {
    String fileName = img_url.substring(img_url.lastIndexOf('/') + 1, img_url.length());
    File file = new File("/storage/emulated/0/rready_images/" + fileName);

    if (file.exists() && !file.isDirectory()) {
        Log.d("Image exists", fileName);

    } else {
        if (fileName.contains(".jpg") || fileName.contains(".gif") || fileName.contains(".png")) {
            new DownloadImagesAsync().execute(img_url);
        } else {
            Log.d("IMAGE DOWNLOAD ", "FAILED FOR " + fileName);

        }

    }
}

下载文件的实际异步任务代码: -

     class DownloadImagesAsync extends AsyncTask<String, String, String> {

        Boolean isSDPresent = android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);

        private String resp;
        int lengthOfFile;

        @Override
        protected String doInBackground(String... params) {


            int count;

            try {
                URL url = new URL(params[0]);
                URLConnection connection = url.openConnection();
                connection.connect();

                lengthOfFile = connection.getContentLength();
                Log.d("ANDRO_ASYNC", "LENGTH OF FILE : " + lengthOfFile);

                String fileName = params[0].substring(params[0].lastIndexOf('/') + 1, params[0].length());
                Log.d("FILENAME", fileName);
                resp = fileName;

                if (isSDPresent) {

                    InputStream inputStream = new BufferedInputStream(url.openStream());
                    OutputStream outputStream = new FileOutputStream("sdcard/rreadyreckoner_images/" + fileName);
                    byte data[] = new byte[1024];
                    long total = 0;
                    while ((count = inputStream.read(data)) != -1) {
                        total += count;
                        outputStream.write(data, 0, count);
                    }

                    outputStream.flush();
                    outputStream.close();
                    inputStream.close();
                } else {
                    InputStream inputStream = new BufferedInputStream(url.openStream());
                    OutputStream outputStream = new FileOutputStream(getFilesDir() + "/rreadyreckoner_images/" + fileName);
                    byte data[] = new byte[1024];
                    long total = 0;
                    while ((count = inputStream.read(data)) != -1) {
                        total += count;
                        outputStream.write(data, 0, count);
                    }

                    outputStream.flush();
                    outputStream.close();
                    inputStream.close();

                }


            } catch (Exception e) {
                e.printStackTrace();
            }
            return params[0];
        }

        @Override
        protected void onPostExecute(String filename) {
            Log.d("PARAM", filename + " Downloaded ");

            String fname = filename.substring(filename.lastIndexOf('/') + 1, filename.length());

            Log.d("LENGTH OF FILE : ", String.valueOf(lengthOfFile));

            if (isSDPresent) {

                File f = new File("/storage/emulated/0/rreadyreckoner_images/" + fname);
                if (f.length() < lengthOfFile) {
                    if (f.delete()) {

                        //  Toast.makeText(RReadySplash.this, "Download was interrupted please try again!", Toast.LENGTH_SHORT).show();
                        Log.d("Del", "File deleted");
                    } else {

                        Log.d("NOTDel", "File not deleted");
                    }
                } else {

                    // dbHandler.updateDownloadStatus(image_id, "YES");

                }

            } else {

                File f = new File("/storage/emulated/0/rreadyreckoner_images/" + fname);
                if (f.length() < lengthOfFile) {
                    if (f.delete()) {

                        Log.d("Del", "File deleted");
                    } else {

                        Log.d("NOTDel", "File not deleted");
                    }
                } else {

//                    dbHandler.updateDownloadStatus(image_id, "YES");


                }


            }


        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();

        }

        @Override
        protected void onProgressUpdate(String... values) {
            Log.d("ANDRO_ASYNC", values[0]);

        }
    }

感谢任何帮助或建议。谢谢。

3 个答案:

答案 0 :(得分:3)

使用异步任务的重点是不阻止主线程。尝试阻止所有操作,直到在异步任务中下载文件可能不是可行的方法,绝对不建议使用。相反,我建议您下载所需的文件并使用在用户第一次安装应用程序时运行的后台服务来存储它们,这样您只需在启动时阅读即可。如果您在下载完成之前设法停止所有工作,您将收到ANR消息。

那么在这种情况下你能做些什么,使用片段和AsyncTaskLoader或者在完成下载后广播意图的后台service代替异步任务,因为只建议异步任务短期操作。通过注册接收器来监听此广播,并在收到加载器或服务的结果后相应地更新UI。

答案 1 :(得分:1)

有很多方法。

例如,您可以使用接口回调。

创建一个界面:

public interface MyCallback {
    public void readycallback(int index_thread);
}

改变班级:

    class DownloadImagesAsync extends AsyncTask<String, String, String> {
private int id = 0;
private    MyCallback callback;
            Boolean isSDPresent = android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);

            private String resp;
            int lengthOfFile;
    public DownloadImagesAsync(int id, MyCallback callback) {
this.id = id;
this.callback = callback;
}
            @Override
            protected String doInBackground(String... params) {


                int count;

                try {
                    URL url = new URL(params[0]);
                    URLConnection connection = url.openConnection();
                    connection.connect();

                    lengthOfFile = connection.getContentLength();
                    Log.d("ANDRO_ASYNC", "LENGTH OF FILE : " + lengthOfFile);

                    String fileName = params[0].substring(params[0].lastIndexOf('/') + 1, params[0].length());
                    Log.d("FILENAME", fileName);
                    resp = fileName;

                    if (isSDPresent) {

                        InputStream inputStream = new BufferedInputStream(url.openStream());
                        OutputStream outputStream = new FileOutputStream("sdcard/rreadyreckoner_images/" + fileName);
                        byte data[] = new byte[1024];
                        long total = 0;
                        while ((count = inputStream.read(data)) != -1) {
                            total += count;
                            outputStream.write(data, 0, count);
                        }

                        outputStream.flush();
                        outputStream.close();
                        inputStream.close();
                    } else {
                        InputStream inputStream = new BufferedInputStream(url.openStream());
                        OutputStream outputStream = new FileOutputStream(getFilesDir() + "/rreadyreckoner_images/" + fileName);
                        byte data[] = new byte[1024];
                        long total = 0;
                        while ((count = inputStream.read(data)) != -1) {
                            total += count;
                            outputStream.write(data, 0, count);
                        }

                        outputStream.flush();
                        outputStream.close();
                        inputStream.close();

                    }


                } catch (Exception e) {
                    e.printStackTrace();
                }
                return params[0];
            }

            @Override
            protected void onPostExecute(String filename) {
                Log.d("PARAM", filename + " Downloaded ");
    if (callback != null) {
callback.readycallback(myid);
}
                String fname = filename.substring(filename.lastIndexOf('/') + 1, filename.length());

                Log.d("LENGTH OF FILE : ", String.valueOf(lengthOfFile));

                if (isSDPresent) {

                    File f = new File("/storage/emulated/0/rreadyreckoner_images/" + fname);
                    if (f.length() < lengthOfFile) {
                        if (f.delete()) {

                            //  Toast.makeText(RReadySplash.this, "Download was interrupted please try again!", Toast.LENGTH_SHORT).show();
                            Log.d("Del", "File deleted");
                        } else {

                            Log.d("NOTDel", "File not deleted");
                        }
                    } else {

                        // dbHandler.updateDownloadStatus(image_id, "YES");

                    }

                } else {

                    File f = new File("/storage/emulated/0/rreadyreckoner_images/" + fname);
                    if (f.length() < lengthOfFile) {
                        if (f.delete()) {

                            Log.d("Del", "File deleted");
                        } else {

                            Log.d("NOTDel", "File not deleted");
                        }
                    } else {

    //                    dbHandler.updateDownloadStatus(image_id, "YES");


                    }


                }


            }

            @Override
            protected void onPreExecute() {
                super.onPreExecute();

            }

            @Override
            protected void onProgressUpdate(String... values) {
                Log.d("ANDRO_ASYNC", values[0]);

            }
        }

使用此类更改主函数

String[] images = Parse_imgJSON.image;
        for (int i = 0; i < images.length; i++) {
            Log.d("Image ", images[i]);
            download_img(images[i], i);
        }




 public void download_img(String img_url, int i) {
        String fileName = img_url.substring(img_url.lastIndexOf('/') + 1, img_url.length());
        File file = new File("/storage/emulated/0/rready_images/" + fileName);

        if (file.exists() && !file.isDirectory()) {
            Log.d("Image exists", fileName);



            } else {
                if (fileName.contains(".jpg") || fileName.contains(".gif") || fileName.contains(".png")) {
                    new DownloadImagesAsync(i, new MyCallback() {
@Override
    public void readycallback(int index_thread) {

    //this is your ready callback

    }
    }).execute(img_url);
                } else {
                    Log.d("IMAGE DOWNLOAD ", "FAILED FOR " + fileName);

                }

            }
    }

不要忘记检查是否使用主UI线程:

如果需要,可以通过此函数包装更新:

@Override
    public void readycallback(int index_thread) {

    //this is your ready callback
    runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    //this is your ready callback in main UI
//I do not remember if onPostExecute is in main UI thread
                }
            });
    }

答案 2 :(得分:1)

我使用ProgressBar来显示更新作为示例。你当然可以选择你喜欢的任何视图。在download_img()我正在递增值,使其显示1/3而不是0/3。

另外,我假设所有这些方法和AsyncTask都在一个单独的java文件中。

ProgressBar mProgress = (ProgressBar) findViewById(R.id.progress_bar);              <------------Here

probressbar.setMax(images.length)                <---------------Here

             for (int i = 0; i < images.length; i++) {
                         Log.d("Image ", images[i]);
                         download_img(images[i], i);
             }

download_img()

public void download_img(String img_url, int i) {          <---------------Here
String fileName = img_url.substring(img_url.lastIndexOf('/') + 1, img_url.length());
File file = new File("/storage/emulated/0/rready_images/" + fileName);

if (file.exists() && !file.isDirectory()) {
    Log.d("Image exists", fileName);

} else {
    if (fileName.contains(".jpg") || fileName.contains(".gif") || fileName.contains(".png")) {
        new DownloadImagesAsync().execute(img_url, ++i);          <------------------Here
    } else {
        Log.d("IMAGE DOWNLOAD ", "FAILED FOR " + fileName);

    }

}
}

的AsyncTask

    class DownloadImagesAsync extends AsyncTask<String, String, String> {

    Boolean isSDPresent = android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);

    private String resp;
    int lengthOfFile, progressStatus;                  <------------Here

    @Override
    protected String doInBackground(String... params) {


        int count;

        try {
            progressStatus=Integer.parseInt(params[1]);               <-----------Here
            URL url = new URL(params[0]);
            URLConnection connection = url.openConnection();
            connection.connect();

            lengthOfFile = connection.getContentLength();
            Log.d("ANDRO_ASYNC", "LENGTH OF FILE : " + lengthOfFile);

            String fileName = params[0].substring(params[0].lastIndexOf('/') + 1, params[0].length());
            Log.d("FILENAME", fileName);
            resp = fileName;

            if (isSDPresent) {

                InputStream inputStream = new BufferedInputStream(url.openStream());
                OutputStream outputStream = new FileOutputStream("sdcard/rreadyreckoner_images/" + fileName);
                byte data[] = new byte[1024];
                long total = 0;
                while ((count = inputStream.read(data)) != -1) {
                    total += count;
                    outputStream.write(data, 0, count);
                }

                outputStream.flush();
                outputStream.close();
                inputStream.close();
            } else {
                InputStream inputStream = new BufferedInputStream(url.openStream());
                OutputStream outputStream = new FileOutputStream(getFilesDir() + "/rreadyreckoner_images/" + fileName);
                byte data[] = new byte[1024];
                long total = 0;
                while ((count = inputStream.read(data)) != -1) {
                    total += count;
                    outputStream.write(data, 0, count);
                }

                outputStream.flush();
                outputStream.close();
                inputStream.close();

            }


        } catch (Exception e) {
            e.printStackTrace();
        }
        return params[0];
    }

    @Override
    protected void onPostExecute(String filename) {
        Log.d("PARAM", filename + " Downloaded ");
        mProgress.setProgress(mProgressStatus);         <----------------Here

        String fname = filename.substring(filename.lastIndexOf('/') + 1, filename.length());

        Log.d("LENGTH OF FILE : ", String.valueOf(lengthOfFile));

        if (isSDPresent) {

            File f = new File("/storage/emulated/0/rreadyreckoner_images/" + fname);
            if (f.length() < lengthOfFile) {
                if (f.delete()) {

                    //  Toast.makeText(RReadySplash.this, "Download was interrupted please try again!", Toast.LENGTH_SHORT).show();
                    Log.d("Del", "File deleted");
                } else {

                    Log.d("NOTDel", "File not deleted");
                }
            } else {

                         // dbHandler.updateDownloadStatus(image_id, "YES");

            }

        } else {

            File f = new File("/storage/emulated/0/rreadyreckoner_images/" + fname);
            if (f.length() < lengthOfFile) {
                if (f.delete()) {

                    Log.d("Del", "File deleted");
                } else {

                    Log.d("NOTDel", "File not deleted");
                }
            } else {

                   //dbHandler.updateDownloadStatus(image_id, "YES");


            }


        }


    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();

    }

    @Override
    protected void onProgressUpdate(String... values) {
        Log.d("ANDRO_ASYNC", values[0]);

    }
}