[英]Waiting for other AsyncTasks' finish in AsyncTask before processing onPostExecute
[英]AsyncTask waiting on other AsyncTasks
我建立了多個asynctasks來處理多個不同的任務。 主要目標是“重置數據”,其中涉及:
今天,我已經通過創建多個“ 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.