2016-10-02 2 views
0

Ткань рассказала мне о нескольких встречах NPE, которые я не могу объяснить. Они происходят на разных устройствах и версиях Android.Невозможный NPE во фрагменте

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) 

И теперь исходный код для деятельности, которая всегда инициализирует экземпляр 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. Он отлично работает на всех моих реальных устройствах и виртуальных устройствах. Я не знаю, почему он пуст на этих сообщенных устройствах.

+0

Где вы инициализируете переменную gameLogic? – Sanjeet

+0

в setter setGameLogic, см. OnCreate –

+0

Что такое 'LeliBaseActivity.onStart()'? Вот где ваш фрагмент активируется. – kichik

ответ

3

Рамки для Android часто нуждаются в восстановлении фрагментов, например, для обработки изменения конфигурации. Состояние экземпляра, такое как ваш CalcLogic, теряется.

Некоторых вариантов крепления его:

  1. Вытащите значение для logic поля от деятельности в onCreate() или другом аналогичном методе раннего жизненного цикла фрагмента.

  2. Позвоните setRetainInstance(true), чтобы экземпляр фрагмента сохранился в некоторых случаях, когда обычно происходит восстановление.

+0

спасибо, я постараюсь –

+0

Это не произошло, так как я переписал эту часть. Благодарю. –

Смежные вопросы