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

Bon*_*i2k 20 android android-asynctask android-fragments

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

使用与Tab-Navigation类似的东西,当用户选择另一个选项卡时,将替换片段.填充片段后,我启动至少一个AsyncTask以从Internet获取一些信息.但是 - 如果用户切换到另一个选项卡,就像我的AsyncTask中的doBackground方法正在执行一样 - 片段被替换,因此我得到一个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
  ...
}
Run Code Online (Sandbox Code Playgroud)

getActivity()并且getResources()因为我的Fragment被替换而导致错误.

我试过的事情:

  • 在我的AsyncTask上调用cancel方法(如果在onPostExecute()执行时替换片段,则不会修复第一个错误,也不会修复第二个错误)
  • 检查是否getActivity()正在null调用this.isDetached()(不是真正的修复,我需要在每次呼叫时检查它getActivity()等等)

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

Nik*_*kov 18

由于AsyncTask在后台运行,您的片段可能会在完成时与其父活动分离.你发现了,你可以isDetached()用来检查.这没有什么不对,你不必每次都检查,只考虑片段和活动生命周期.

另外两种选择:

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

  • 只有在您自己显式分离片段时才应使用isDetached().否则,您应该使用isAdded()来处理系统破坏活动和片段之间链接的情况. (8认同)