产生一个耗时的计算线程是很常见的。稍后,我们需要用计算结果更新 Activity
或 Fragment
。
一直以来,我都遵循以下准则。到目前为止,它对我来说效果很好。
AsyncTask 需要onPostExecute UI Fragment
- 使用
setRetainInstance(true)
无 UI fragment 。 - 使用
setTargetFragment
和getTargetFragment
技术 - 请引用https://stackoverflow.com/a/12303649/72437
AsyncTask 需要 onPostExecute UI Activity
- 使用
setRetainInstance(true)
无 UI fragment 。 - 使用
onAttach
和onDetach
来存储对Activity
的引用。 Google 似乎不鼓励使用getActivity
。 http://developer.android.com/guide/components/fragments.html - 请引用https://stackoverflow.com/a/16305029/72437
但是,对于从 View
派生的类,情况如何?我计划从自定义 View
启动 AsyncTask
。但是,如何onPostExecute
返回View
?
我这样问的原因是,在我的自定义 View 中,某些触摸事件会触发它使用新的位图重绘自身。生成新位图非常耗时。因此,我计划启动一个 AsyncTask,生成这样的位图,然后传回自定义 View 。但是,配置更改可能会导致重新创建自定义 View 。因此,我需要确保我的 AsyncTask 在 onPostExecute
期间可以有正确的 View 引用。
最佳答案
假设您仅将 AsyncTask
用于与绘图相关的操作(否则您真的应该重新审视您的逻辑 - 正如评论所建议的那样),您可以直接在中创建 AsyncTask
您的自定义 View
类:
class MyView extends View {
private MyAsyncTask currentTask = null;
// View details
@Override
public void onAttachedToWindow() {
currentTask = new MyAsyncTask(this);
currentTask.execute();
}
@Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (currentTask != null) {
currentTask.cancel(true);
currentTask = null;
}
}
static class MyAsyncTask extends AsyncTask<Void, Void, Bitmap> {
private WeakReference<MyView> viewRef;
MyAsyncTask(MyView view) {
viewRef = new WeakReference<>(view);
}
// background task implementation
@Override
public void onPostExecute(Bitmap bitmap) {
MyView view = viewRef.get();
if (view == null) {
return;
}
// you now can safely update your view - we're on UI thread
}
}
}
这就是安全实现的样子。它有一些缺点和重要的部分:
- 在任何情况下,您的
AsyncTask
都不应持有对View
的强引用(这就是类被声明为static
并持有WeakReference< 的原因
到View
) - 当您不再对
AsyncTask
的结果感兴趣时 - 取消它 - 此实现只会丢弃来自已取消的
AsyncTask
的可能有用的结果。如果这是问题 - 我建议从View
中完全删除AsyncTask
并搜索其他解决方案(单独的Executor
或HandlerThread
).
AsyncTask
的 onPostExecute
也会从启动它的同一个循环线程中调用(在你的例子中是主线程,所以如果你从Activity
或 View
,或其他任何地方,这完全取决于管理这些任务的难度)。
关于android - 从自定义 View 启动 AsyncTask 的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26913133/