Почему Fragment onCreate() иногда вызывается до Activity onCreate()?

Недавно я столкнулся с трудной проблемой. NPE возникает, когда фрагмент пытается инициализировать ArrayAdapter данными из Activity. Список по умолчанию, инициализированный в методе Activity onCreate:

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // ...
    mAccounts = new ArrayList<>();
    // ...
}

@Override
public List<Account> getAccounts(){
    return mAccounts;
}

Фрагмент создает адаптер списка также в его onCreate():

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setRetainInstance(true);
    setHasOptionsMenu(true);

    //mAccountProvider is an interface implemented by the activity
    mAccounts = mAccountProvider.getAccounts();

    mAccountAdapter = new AccountAdapter(getActivity(), R.layout.account_list_item, mAccounts);
}

NPE возникает внутри AccountAdapter, когда вызывается метод getCount(). Причина в том, что mAccounts является нулевым. Проблема возникает редко, и я не смог ее воспроизвести.

Когда возможно, что фрагмент onCreate() вызывается перед активностью onCreate()? Согласно исходному коду, Fragment onCreate() отправляется в Activity onCreate(). Почему это вызвано после того, как Activity onCreate() завершила выполнение?

Ответы

Ответ 1

Обратный вызов активности не вызывается после фрагментов; Фрагмент вызывается во время действия.

Инициализировать mAccounts перед вызовом super.onCreate() в Activity.onCreate()

Ответ 2

onCreate() вашего фрагмента можно вызвать до onCreate() метода onCreate() вашей активности. У вас есть onActivityCreated() вызов onActivityCreated() в вашем фрагменте и onCreateView(). Вы можете использовать любой из них - он выполняется после метода onCreate.

Ответ 3

Эта ошибка может быть воспроизведена, включив функцию "Dont't keep activities" в настройках разработчика. Я столкнулся с подобной проблемой и решил с помощью решения, предоставленного FunkTheMonk.

Ответ 4

Недавно столкнулся с проблемой. См. Трассировку стека внизу.

Как заявил FunkTheMonk, авария связана с тем, что ваш собственный код onCreate() в вашей деятельности (сразу после super.onCreate()) выполняется после вашего настроенного кода onCreate() в вашем фрагменте (сразу после super.onCreate( ))

Если вам действительно нужно, чтобы ваш обратный вызов был успешно выполнен после всей операции onCreate(), поместите фрагменты кода в onActivityCreated() а не в onCreate()

В противном случае вышеупомянутое условие произойдет, когда ваша память будет низкой и активность будет переработана.

По моему опыту, когда MyActivity отправляет намерение, приложение падает после того, как я вернусь в MyFragment, нажав клавишу "Назад".

Caused by: java.lang.NullPointerException
   at MyFragment.onCreate(MyFragment.java:20)
   at android.support.v4.app.Fragment.performCreate(Fragment.java:1939)
   at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1029)
   at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1248)
   at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1230)
   at android.support.v4.app.FragmentManagerImpl.dispatchCreate(FragmentManager.java:2037)
   at android.support.v4.app.FragmentController.dispatchCreate(FragmentController.java:154)
   at android.support.v4.app.FragmentActivity.onCreate(FragmentActivity.java:289)
   at android.support.v7.app.AppCompatActivity.onCreate(AppCompatActivity.java:58)
   at MyActivity.onCreate(MyActivity.java:129)
   at android.app.Activity.performCreate(Activity.java:5248)
   at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1110)
   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2162)
   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2257) 
   at android.app.ActivityThread.access$800(ActivityThread.java:139) 
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1210) 
   at android.os.Handler.dispatchMessage(Handler.java:102) 
   at android.os.Looper.loop(Looper.java:136) 
   at android.app.ActivityThread.main(ActivityThread.java:5086) 
   at java.lang.reflect.Method.invokeNative(Native Method) 
   at java.lang.reflect.Method.invoke(Method.java:515) 
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785) 
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601) 
   at dalvik.system.NativeStart.main(Native Method) 

Ответ 5

Возможно, я слишком поздно, чтобы ответить, но все же. Я столкнулся с этим несколько дней назад. Это происходит, когда вы используете динамические фрагменты, а в макете вы используете тег фрагмента для отображения фрагмента. Вместо этого используйте макет (предпочтительно FrameLayout). Предположим, вы использовали библиотеку фрагментов поддержки.

Это стоит попробовать.