碎片中不可能的NPE

时间:2016-10-02 20:02:13

标签: android android-fragments

Fabric告诉我一些我无法解释的NPE事件。它们发生在不同的设备和Android版本上。

Fatal Exception: java.lang.RuntimeException: Unable to start activity ComponentInfo{lelisoft.com.lelimath/lelisoft.com.lelimath.activities.CalcActivity}: java.lang.NullPointerException
   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2328)
   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2386)
   at android.app.ActivityThread.access$900(ActivityThread.java:169)
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1277)
   at android.os.Handler.dispatchMessage(Handler.java:102)
   at android.os.Looper.loop(Looper.java:136)
   at android.app.ActivityThread.main(ActivityThread.java:5476)
   at java.lang.reflect.Method.invokeNative(Method.java)
   at java.lang.reflect.Method.invoke(Method.java:515)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
   at dalvik.system.NativeStart.main(NativeStart.java)
Caused by java.lang.NullPointerException
   at lelisoft.com.lelimath.fragment.CalcFragment.setupPlay(CalcFragment.java:253)
   at lelisoft.com.lelimath.fragment.CalcFragment.onActivityCreated(CalcFragment.java:86)
   at android.support.v4.app.Fragment.performActivityCreated(Fragment.java:2089)
   at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1133)
   at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1290)
   at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1272)
   at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:2149)
   at android.support.v4.app.FragmentController.dispatchActivityCreated(FragmentController.java:201)
   at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:600)
   at android.support.v7.app.AppCompatActivity.onStart(AppCompatActivity.java:178)
   at lelisoft.com.lelimath.activities.LeliBaseActivity.onStart(LeliBaseActivity.java:94)
   at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1177)
   at android.app.Activity.performStart(Activity.java:5461)
   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2301)
   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2386)
   at android.app.ActivityThread.access$900(ActivityThread.java:169)
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1277)
   at android.os.Handler.dispatchMessage(Handler.java:102)
   at android.os.Looper.loop(Looper.java:136)
   at android.app.ActivityThread.main(ActivityThread.java:5476)
   at java.lang.reflect.Method.invokeNative(Method.java)
   at java.lang.reflect.Method.invoke(Method.java:515)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
   at dalvik.system.NativeStart.main(NativeStart.java)

现在,Activity的源代码始终初始化GameLogic实例并将其传递给onCreate()中的片段:

public class CalcActivity .. {
 GameLogic gameLogic;

 protected void onCreate(Bundle state) {
    setContentView(R.layout.act_calc);
    setGameLogic(new CalcLogicImpl());
    calcFragment = new CalcFragment();
    calcFragment.setLogic((CalcLogic) gameLogic);
    initializeCalcFragment(false);
 }

private void initializeCalcFragment(boolean replace) {
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    if (replace) {
        transaction.replace(R.id.calc_content, calcFragment);
    } else {
        transaction.add(R.id.calc_content, calcFragment);
    }
    transaction.commit();
}

public void setGameLogic(GameLogic gameLogic) {
    this.gameLogic = gameLogic;
}

然后有一个CalcFragment:

public class CalcFragment extends LeliBaseFragment {
 CalcLogic logic;

 public void setLogic(CalcLogic logic) {
    this.logic = logic;
 }

 public void onActivityCreated(Bundle state) {
    setupPlay();
 }

这里NPE失败了:

private void setupPlay() {
    formulas = logic.generateFormulas();
}

流程清晰,没有其他属性分配。创建活动,实例化和设置属性,创建片段并传递属性。然后片段在onActivityCreated中初始化,但有时属性为null。它适用于我所有的真实设备和虚拟设备。我不知道为什么它们在那些报告的设备上是空的。

1 个答案:

答案 0 :(得分:3)

Android框架通常需要重新实例化片段,以便处理配置更改。您的CalcLogic等实例状态已丢失。

修复它的一些选项:

  1. 从片段logic或其他类似的早期生命周期方法中的活动中提取onCreate()字段的值。

  2. 调用setRetainInstance(true)使片段实例在某些通常会发生重新安装的情况下生效。