当前位置: 代码迷 >> Android >> AsyncTask等待其他AsyncTasks
  详细解决方案

AsyncTask等待其他AsyncTasks

热度:75   发布时间:2023-08-04 12:32:42.0

我建立了多个asynctasks来处理多个不同的任务。 主要目标是“重置数据”,其中涉及:

  1. 删除数据库中所有现有数据,表x
  2. 删除所有与数据相关的现有本地文件
  3. 提交网络请求以下载将提供“刷新”数据的JSON
  4. 解析JSON
  5. 将JSON存储在数据库中
  6. 根据JSON数据下载新的本地文件(即将包含图像URL)
  7. 存储下载的文件

今天,我已经通过创建多个“ sub” -AsyncTasks来完成工作的主AsyncTask“实现”了。 此任务的代码如下:

private class GetMetaDataTask extends AsyncTask<String, Integer, String> {
    private Context context;
    private ProgressDialog dialog;
    private List<MatchDetail> results;
    private long accountId;

    public GetMetaDataTask(Context c) {     
        this.context = c;
        this.dialog = new ProgressDialog(context);
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        if (dialog != null) {
            dialog.setMessage("Downloading JSON...");
            dialog.show();
        }
    }

    @Override
    protected String doInBackground(String... inputs) {     
            /** Items **/
            List <Item> items = stats.getItemsMeta();
            List <MetaImageDownloader> metaDownloaders = new ArrayList<MetaImageDownloader>();
            if (items.size() > 0) {
                new ResourceHelper(null, context).deleteLocalImages(ResourceHelper.PATH_ITEMS);
                db.deleteItems();
                for (Item i: items) {           
                    //Store in database
                    db.storeItem(i);
                    //Download images
                    new MetaImageDownloader(context, i.getItemImg(),MetaImageDownloader.JOB_DOWNLOAD_ITEM)).execute();
                }

            }
        return null;
     }

     protected void onProgressUpdate(Integer... progress) {
     }
     @Override
     protected void onPostExecute(String result) {

         db.close();
            if (dialog != null) 
                dialog.dismiss();
     }
}

下面是MetaImageDownloader的doInBackground代码:

protected Void doInBackground(String... imgTypes) {
    ResourceHelper rh = new ResourceHelper(null, context);
    if (jobType == JOB_DOWNLOAD_ITEM) { 
        bmp = rh.getBitmapFromURL(getItemImageUrl(downloadCode));
        rh.saveImageLocally(bmp, ResourceHelper.PATH_ITEMS, downloadCode);
        if (bmp != null)
            bmp.recycle();

    } 
    ...

要分解,

1)删除所有现有数据:

db.deleteItems();

2)删除所有与数据相关的现有本地文件:

new ResourceHelper(null, context).deleteLocalImages(ResourceHelper.PATH_ITEMS);

3/4)提交网络请求以下载将提供“刷新”数据并解析的JSON:

List <Item> items = stats.getItemsMeta();

5)将JSON存储在数据库中: db.storeItem(i);

6)根据JSON数据下载新的本地文件:

new MetaImageDownloader(context, i.getItemImg(),MetaImageDownloader.JOB_DOWNLOAD_ITEM)).execute();

(在MetaImageDownloader内部)-bmp bmp = rh.getBitmapFromURL(getItemImageUrl(downloadCode));

7)存储下载的文件:

(在MetaImageDownloader内部) rh.saveImageLocally(bmp, ResourceHelper.PATH_ITEMS, downloadCode);

-

ew! 现在,#6是每个项目都运行的新AsyncTask,可一次同时下载所有图像。 我面临的挑战是如何确定所有MetaImageDownloader AsyncTasks何时完成。 我可以为每个下载的图像获取onPostExecute,但在完成所有161个操作后无法获取。

问题1-我是否通过在AsyncTask中创建AsyncTask来违反标准? 我知道最大的问题是无法从这些“ sub-AsyncTasks”更新UI

问题2-所有161个MetaImageDownloader AsyncTasks完成后,如何通知UI?

更新:我创建了一个新功能来执行#6/7:

public void batchDownloadSaveImages(List<Item> items, List<Hero> heroes, String heroImgTypes[]) throws ExecutionException, InterruptedException {
List<Runnable> requests = new ArrayList<Runnable>();

    final ExecutorService pool = Executors
            .newFixedThreadPool(Const.MAX_THREAD_POOL);
    int reqCounter = 1;

    for (final Item item : items) {
        requests.add(new Runnable() {

            @Override
            public void run() {     
                Bitmap bmp = getBitmapFromURL(getItemImageUrl(item.getItemImg()));
                saveImageLocally(bmp, ResourceHelper.PATH_HEROES, item.getItemImg());
            }
        });
        reqCounter++;
    }

    List<Future> runnables = new ArrayList<Future>();

    for (Runnable request : requests) {
        runnables.add(pool.submit(request));
    }

    for (Future future : runnables) {
        synchronized (this) {
            System.out.println("- Received request. " + --reqCounter
                    + " requests to go!");
        }
    }

    // Wait till everything has calmed down!
    pool.shutdown();
}

您要实现的目标的标准模式如下:

function on_all_tasks_done() {
  // do something
}

tasks = generate_async_taks()
var nb_tasks = tasks.size()
var callback = function() {
  nb_tasks--
  if (nb_tasks == 0) on_all_tasks_done();
};

for (var i = 0; i < nb_tasks; i++) {
  var task = tasks[i]
  task.execute_then_invoke(callback)
}

扩展大注释部分:这个问题开始于:如果我有一组任务并异步运行它们,我如何对'all_tasks_done'事件作出反应。 我回答了这个问题。 现在您基本上是在问一些东西,例如:

“我应该如何构造我的代码?” 或“编写可维护的异步代码的最佳策略是什么?”

这类问题很难回答,而且对您而言,缺少必要的术语。 恐怕我无能为力了:)