我最近将我的activity转换为Fragments。
使用类似于tab - navigation的东西,当用户选择另一个tab时,片段被替换。片段填充后,我开始至少一个AsyncTask从互联网获取一些信息。然而,如果用户切换到另一个选项卡,就像doBackground-method从我的AsyncTask正在执行-片段是取代,因此我得到一个NullPointerException
在标记行:
@Override
protected Object doInBackground(Object... params) {
...
String tempjson = helper.SendPost(getResources().getText(R.string.apiid)); //ERROR: Fragment not attached
...
}
protected onPostExecute(Object result) {
...
getActivity().getContentResolver() //NULLPOINTEREXCEPTION
getView().findViewById(R.id.button) //NULL
...
}
getActivity()
和getResources()
导致错误,因为我的Fragment被替换了。
我尝试过的事情:
- 在我的AsyncTask上调用取消方法(不会修复第一个错误,也不会修复第二个错误,如果片段被替换,而
onPostExecute()
被执行) - 检查
getActivity()
是否为null
或调用this.isDetached()
(不是真正的修复,我需要检查它每当我调用getActivity()
等)
所以我的问题是:什么是最好的摆脱这些AsyncTask问题?我在使用Activities时没有遇到这些问题,因为它们不会在选项卡更改时被"杀死"/分离(这会导致更高的内存使用-这就是我喜欢切换到Fragments的原因)
由于AsyncTask
在后台运行,您的片段可能会在完成时脱离其父活动。正如你所发现的,你可以使用isDetached()
来检查。这没有什么问题,你不必每次都检查,只需要考虑片段和活动的生命周期。
其他两个选择:
- 使用加载器,它们可以更好地处理片段
- 移动你的AsyncTask加载到父活动,并使用接口从片段解耦。该活动将知道片段是否存在,并相应地采取行动(如果片段消失,可能会丢弃结果)。
今天我遇到了同样的问题:当我改变fragment
被显示,如果AsyncTask
还没有完成,它试图访问view
填充它与一些更多的元素,它会返回一个NullPointerException
。
我解决了重写片段生命周期的一个方法:onDetach()
的问题。这个方法在fragment
从activity
分离之前被调用。
你需要做的是在AsyncTask
上调用cancel()
方法。这将停止任务执行,避免NullPointerExecption
。
以下是onDetach()
的示例:
@Override
public void onDetach() {
super.onDetach();
task.cancel(true);
}
查看此页面以获取有关fragment生命周期的更多信息:http://developer.android.com/reference/android/app/Fragment.html#Lifecycle这个可以查看更多关于取消任务的信息:http://developer.android.com/reference/android/os/AsyncTask.html
您是否尝试在您的片段类的onCreate()
函数中调用setRetainInstance(true);
?