我从Fragments启动大部分网络调用,然后使用回调告诉Fragment网络任务是否成功,并相应地更新ui。
在罕见的场合(.25%的会话)中,由于getActivity()在我的回调中的代码运行时返回null,我的程序因空指针异常而崩溃。我知道我可以对getActivity()使用空检查来防止这种情况发生,但是处理这个问题的最佳做法是什么?
空检查似乎只是一个防撞工具,因为程序仍然需要来自网络任务的数据。
代码如下所示:
private void queryServer() {
// networking task should query server for user id, if successful store it
// in user preferences to be accessed by fragment in callback
new networkingTask(new VolleyCallback() {
@Override
public void onSuccess() {
// code below needs null check on getActivity - but what else?
mUserId = new UserPreferences(getActivity()).getUserId();
}
@Override
public void onFail() {
// booooo
}
});
}
答案 0 :(得分:1)
正如我在上面的评论中所述,可能发生的事情是系统正在停止或销毁活动/碎片对。这将由于各种原因而发生,例如屏幕方向改变。因为您的处理程序是片段对象上的方法,所以在调用返回时您正在使用“死”片段。有几种模式可以解决这个问题。简而言之,您需要让您的处理程序了解当前片段,并且您可以通过使用生命周期方法来实现此目的。
以下是您可以使用的模式示例。我试图尽量减少这个例子。
import android.app.Activity;
import android.app.Fragment;
public class MyFragment extends Fragment {
// This is static so that it will not go out of scope when the original
// fragment is destroy. This allows it to be access from all MyFragment
// instances.
static MyResponseProcessor processor = new MyResponseProcessor();
// This will be the class that handles your network call.
public static class MyResponseProcessor {
// This instance variable is alway a reference to the currently displayed fragment.
private Fragment activeFragement;
public void setActiveFragement(Fragment activeFragement) {
this.activeFragement = activeFragement;
}
// This method, which is for demonstration purposes, shows how you would handle a network response.
public void handleResponse(SomeResponseObject) {
if (activeFragement != null) {
// Now you can get the activity
Activity activity = activeFragement.getActivity();
} else {
// Yes it is possible that there is no active fragment.
// If the user has stayed on the same screen, then the
// fragment of interest will likely be re-created, and
// this window of time with no fragment will be brief.
//
// Note that this null-check is very different than the
// null-check you describe. In your case the reference is
// guaranteed to be null forever. In this case, the reference
// will eventually become non-null.
}
}
}
@Override
public void onStart() {
super.onStart();
// At this point in the fragment lifecycle, the fragment is both running and is attached to an Activity.
// Thus "getActivity" calls are safe from this point onward.
processor.setActiveFragement(this);
}
@Override
public void onStop() {
super.onStop();
// At this point in the fragment lifecycle, the fragment has been stopped and is about to lose its connection to the activity.
// So after this point, calls to "getActivity" are probably not safe.
// DISCLAIMER - I have not tested this. You might want to do this in a
// different method such as "onDestroyView()"
processor.setActiveFragement(null);
}
}