执行AsyncTask时替换碎片 - getActivity()上的NullPointerException

时间:2011-11-27 21:47:36

标签: android android-asynctask android-fragments

我最近将我的活动转换为碎片。

使用类似于Tab-Navigation的内容,当用户选择另一个选项卡时,会替换片段。 填充片段后,我启动至少一个AsyncTask以从Internet获取一些信息。但是 - 如果用户切换到另一个选项卡,就像我的AsyncTask中的doBackground方法正在执行一样 - 片段被替换,因此我在标记的行中得到NullPointerException:< / p>

@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()会导致错误,因为我的片段已被替换。

我尝试过的事情:

  • 在我的AsyncTask上调用cancel方法(如果在执行onPostExecute()时替换片段,则不会修复第一个错误,也不会修复第二个错误)
  • 检查getActivity()null还是致电this.isDetached()(不是真正的解决方案,每当我致电getActivity()时我都需要检查一下等等)

所以我的问题是:摆脱这些AsyncTask问题最好的是什么?我没有使用活动这些问题,因为它们没有在标签更改时被“杀死”/分离(这导致更高的内存使用量 - 我之所以想切换到碎片的原因)

3 个答案:

答案 0 :(得分:18)

由于AsyncTask在后​​台运行,因此您的片段在完成时可能会与其父活动分离。如您所知,您可以使用isDetached()进行检查。这没有什么不对,你不必每次都检查,只考虑片段和活动生命周期。

另外两种选择:

  • 使用加载器,它们旨在使用片段更好地播放
  • 将AsyncTask加载移动到父活动,并使用接口从片段中解耦。活动将知道片段是否存在,并相应地采取行动(如果片段消失,可能会丢弃结果)。

答案 1 :(得分:4)

今天我遇到了同样的问题:如果fragment尚未完成,我更改了显示的AsyncTask,并尝试访问view以填充它更多元素,它将返回NullPointerException

我解决了覆盖片段生命周期的一种方法的问题:onDetach()。在fragmentactivity分离之前的那一刻调用此方法。

您需要做的是在cancel()上调用AsyncTask方法。这将阻止任务执行,避免NullPointerExecption

以下是onDetach()的示例:

@Override
public void onDetach() {
    super.onDetach();
    task.cancel(true);
}

检查此页面以获取有关片段生命周期的更多信息: http://developer.android.com/reference/android/app/Fragment.html#Lifecycle 这是为了查看有关取消任务的更多信息: http://developer.android.com/reference/android/os/AsyncTask.html

答案 2 :(得分:-1)

您是否尝试在片段类的setRetainInstance(true);函数中调用onCreate()