我已经构建了多个asynctasks来处理多个不同的任务。主要目标是“重置数据”,其中包括:
今天,我已经通过一个主要的AsyncTask'实现'了这个,它创建了多个'sub'-AsyncTasks来完成工作。以下任务代码:
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&amp;解析:
List <Item> items = stats.getItemsMeta();
5)将JSON存储在数据库中
db.storeItem(i);
6)根据JSON数据下载新的本地文件:
new MetaImageDownloader(context, i.getItemImg(),MetaImageDownloader.JOB_DOWNLOAD_ITEM)).execute();
(在MetaImageDownloader内) - bmp = rh.getBitmapFromURL(getItemImageUrl(downloadCode));
7)存储下载的文件:
(在MetaImageDownloader内) - rh.saveImageLocally(bmp, ResourceHelper.PATH_ITEMS, downloadCode);
-
呼!现在,#6是每个Item运行的新AsyncTask,可以同时同时下载所有图像。我遇到的挑战是能够确定所有 MetaImageDownloader AsyncTasks何时完成。每个下载的图像都可以获得PostExecute,但是当所有161个图像都已完成时,我不能。
问题1 - 我是否通过在AsyncTask中创建AsyncTasks来破坏标准?我知道最大的问题是无法从这些'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();
}
答案 0 :(得分:0)
您尝试实现的标准模式如下:
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'事件作出反应。我回答了这个问题。现在你基本上都在问东西,比如:
'我应该如何构建我的代码?'或者'编写可维护异步代码的最佳策略是什么?'
这些问题不容易回答,更多的是你缺乏必要的术语。我担心我能做的只有这么多:)