我已经读过在AsyncTask
中执行Activity
的缺点是该任务无法很好地应对配置更改,因为AsyncTask
的生命周期并未受到限制在Activity
生命周期。因此,如果任务应更新活动的UI,但同时Activity
因配置更改而被销毁,则AsyncTask
不知道新创建的Activity
的任何内容因此它没有机会更新它。这也可能导致内存泄漏。
解决方法建议使用无头Fragment
(Fragment
没有UI),只是为了执行AsyncTask
,因为它可以在配置更改后继续存在。我不理解,它是如何成为一种可行的方法,因为Activity
及其观点在任何情况下都已被破坏。例如:
public MyFragment extends Fragment {
private SomeAsync myAsync = new SomeAsync();
private WeakReference<View> someActivityView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
public void setActivityView(View View) {
someActivityView = new WeakReference<View>(view);
}
...
class SomeAsync extends AsyncTask<Void, Integer, Object> {
protected Object doInBackground(Void... args) {
...
}
protected void onPostExecute(Object result) {
doUpdate(someActivityView, result);
}
}
}
someActivityView
是属于View
的{{1}},并且设置为要更新的Activity
。
我认为在Fragment
再次创建时配置发生变化时不会保留someActivityView
,因此在这种情况下使用无头Activity
有什么好处?
答案 0 :(得分:2)
是的,你读到的关于AsyncTask的内容是真的,是的viewLess片段是一种解决方法。
使用片段做一些事情的一般想法是,它可以访问当前活动活动中的任何活动。这样,您不应使用public void setActivityView(View View) {
存储实际视图,而应仅存储此视图的 id ,并在需要时在活动中找到它。
我会复制你的代码并在其上更改一些内容以显示结果。但还有其他方法可以做到这一点。我最后会简要地谈谈它们。
public MyFragment extends Fragment {
private SomeAsync myAsync = new SomeAsync();
private int viewId = -1;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
// restore the view id
if(savedInstanceState != null && savedInstanceState.containsKey("myViewId")){
viewId = savedInstanceState.getInt("myViewId");
}
}
@Override
public void onSaveInstanceState (Bundle outState) {
super.onSaveInstanceState(outState);
// save the view ID
if(viewId > 0) {
outState.putInt("myViewId", viewId);
}
}
public void setActivityView(View View) {
viewId = view.getId();
}
...
class SomeAsync extends AsyncTask<Void, Integer, Object> {
protected Object doInBackground(Void... args) {
...
}
protected void onPostExecute(Object result) {
Activity activity = getActivity();
if(viewId > 0 && activity != null) {
View view = activity.findViewById(viewId);
doUpdate(view, result);
}
}
}
}
是的,有必要保存ID,因为还有其他原因导致您的活动被杀死(例如,进入后台并且系统内存不足);
<强>备选方案:强>
setArguments(bundle)
。AsyncTask
的方法的接口。然后onPostExecute
调用getActivity
,投射到此界面并将结果直接传递给活动。