簡體   English   中英

AsyncTask等待其他AsyncTasks

[英]AsyncTask waiting on other AsyncTasks

我建立了多個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'事件作出反應。 我回答了這個問題。 現在您基本上是在問一些東西,例如:

“我應該如何構造我的代碼?” 或“編寫可維護的異步代碼的最佳策略是什么?”

這類問題很難回答,而且對您而言,缺少必要的術語。 恐怕我無能為力了:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM