问题描述
我建立了多个asynctasks来处理多个不同的任务。 主要目标是“重置数据”,其中涉及:
- 删除数据库中所有现有数据,表x
- 删除所有与数据相关的现有本地文件
- 提交网络请求以下载将提供“刷新”数据的JSON
- 解析JSON
- 将JSON存储在数据库中
- 根据JSON数据下载新的本地文件(即将包含图像URL)
- 存储下载的文件
今天,我已经通过创建多个“ 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();
}
1楼
您要实现的目标的标准模式如下:
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'事件作出反应。 我回答了这个问题。 现在您基本上是在问一些东西,例如:
“我应该如何构造我的代码?” 或“编写可维护的异步代码的最佳策略是什么?”
这类问题很难回答,而且对您而言,缺少必要的术语。 恐怕我无能为力了:)