在我的应用程序中,当用户点击"保存产品"在AsyncTask中启动了一长串网络操作。
同时,如果用户打开导航抽屉并单击菜单项,则使用另一个AsyncTask,以便加载数据不会阻止UI,这样我就可以防止导航抽屉以一种活泼的方式关闭,而是顺利。
问题是第二个AsyncTask显然等待第一个完成,然后它打开新选择的菜单项。在用户点击它几秒钟后,导航抽屉保持打开状态。
当我将要从AsyncTask打开的菜单项的加载数据切换到主线程时,导航抽屉立即关闭(但是滞后/时髦,不知道什么是更好的词)
那么如何将这个AsyncTask(关闭导航抽屉的那个)分配给另一个线程,这样它就不会等到第一个完成它才能启动?或者有没有办法指导两者并行运行?
答案 0 :(得分:3)
来自Android文档:
执行顺序
首次引入时,AsyncTasks在单个后台线程上串行执行。从DONUT开始,这被改为一个线程池,允许多个任务并行运行。从HONEYCOMB开始,任务在单个线程上执行,以避免由并行执行引起的常见应用程序错误。
如果您真的想要并行执行,可以使用THREAD_POOL_EXECUTOR调用executeOnExecutor(java.util.concurrent.Executor,Object [])。
http://developer.android.com/reference/android/os/AsyncTask.html
通常,如果您想要执行大量线程或长时间运行操作,则不建议使用AyncTasks。您最好使用ThreadPoolExecutor或ScheduledThreadPoolExecutor
答案 1 :(得分:1)
正如Tim B建议的那样,THREAD_POOL_EXECUTOR会为你做到这一点:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
} else {
asyncTask.execute(params);
}
答案 2 :(得分:1)
我的建议是使用AsyncTaskLoader而不是AsyncTask。
AsyncTasks有几个问题:
使用Loaders(http://developer.android.com/reference/android/content/AsyncTaskLoader.html),所有这些问题都已过时。 IMO的主要区别在于它们只进行后台处理,并在完成后报告回来让Activity / Fragment执行ui部分。它们还可以优雅地处理配置更改,这意味着ui部分(活动/片段)和Loader可以在这样的更改后“重新连接”,无需在屏幕旋转后启动新的Loader。一些实现(即CursorLoader)也能够监视对底层数据的更改并自动重新查询(尽管不太相关)。
最后但并非最不重要(回答原始问题),启动新的AsyncTaskLoader永远不会阻止正在运行的线程:
LoaderManager loaderMgr = getLoaderManager();
loaderMgr.initLoader(LOADER_ID, null, this);
initLoader是一个非阻塞调用,并且将始终立即返回。
以下是AsyncTaskLoader的最基本示例:
LoaderManager loaderMgr = getLoaderManager();
loaderMgr.initLoader(LOADER_ID, null, new LoaderManager.LoaderCallbacks<Result>() {
@Override
public Loader<Result> onCreateLoader(int id, Bundle args) {
return new BackgroundTask(maybe some parameters...);
}
@Override
public void onLoaderReset(Loader<Result> loader) {}
@Override
public void onLoadFinished(Loader<Result> loader, Result data) {
// here we update the ui
}
}
class BackgroundTask extends AsyncTaskLoader<Result> {
public BackgroundTask(Context context) {
super(context);
}
@Override
public Result loadInBackground() {
// do the background processing
}
}
虽然这看起来像很多样板代码,但它非常简单,并且很好地显示了后台处理(在BackgroundTask中)和ui部分的分离。
我知道OP可能只是寻找快速修复,其他答案提供了这一点。另一方面,AsyncTaskLoader可能是长期发展的方式。
http://developer.android.com/reference/android/content/AsyncTaskLoader.html