问题 为什么片段的onCreate()有时在Activity的onCreate()之前被调用?


最近我遇到了一个难以重现的问题。 当片段尝试使用Activity中的数据初始化ArrayAdapter时,会发生NPE。在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() 在活动中发送 的onCreate()。为什么在Activity的onCreate()完成执行后调用呢?


10137
2018-05-18 08:05


起源

不,这是不可能的。 - Blackbelt
您应该发布更多有关您的片段在您的活动中显示的代码。 - jobcrazy
我同意@Ilya Vorobiev。调用活动的super.onCreate()时,将调度片段的onCreate()。问题是为什么在大多数情况下它是在Activity的onCreate之后执行的。 - Zzokk


答案:


片段后不调用Activities回调;片段是在活动期间调用的。

初始化 mAccounts 在打电话之前 super.onCreate() 在 Activity.onCreate()


6
2018-05-19 08:16



谢谢你的提示。肯定有几种方法可以解决这个问题。问题是为什么行为不同。 onCreate()是如何准确触发的,以及为什么它有时会在activity的onCreate()之后发生。 - Zzokk


onCreate() 您的片段之前可以调用 onCreate() 您的活动方法已经完成。你有 onActivityCreated() 你片段中的回调和 onCreateView()。你可以使用它 - 它之后执行 onCreate 活动方法。


5
2018-05-18 08:16



你知道确切的情况吗?正如我所提到的,这个问题很少被复制。 - Zzokk
发生此问题时有很多情况。如果您查看FragmentActivity的onCreate()方法,您将看到该活动首先将自身附加到片段,然后执行super.onCreate()。因此,无法保证在片段的onCreate()之前执行代码。 - Ilya Vorobiev
好吧,当问题100%可重复时,我会理解它,因为我的片段的onCreate()在活动的onCreate()之前被调用。我想我应该编辑这个问题。它应该颠倒过来。为什么片段的onCreate()在activiy的onCreate()之后被调用,即使它是在Activty的onCreate()中调度的。 - Zzokk
通常,当由于活动重新创建而恢复片段时会发生这种情况。首次启动活动时,您手动创建片段(在super.onCreate()之后),但在重新创建活动时,会在super.onCreate()中的某些代码中重新创建片段。 - lujop


通过在开发人员选项中启用“不要保留活动”,可以重现此错误。我也遇到过类似的问题,并使用FunkTheMonk提供的解决方案解决了。


2
2017-07-22 02:08





最近遇到了这个问题。请参阅底部的堆栈跟踪。

正如FunkTheMonk所说,崩溃的原因是你的Activity中的自定义onCreate()代码(在super.onCreate()之后)在你的Fragment中定制的onCreate()代码之后执行(紧跟在super.onCreate之后) ))

如果您确实需要在整个Activity的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) 

1
2018-02-27 11:42





我可能为时已晚,无法回答。我几天前遇到过这个。当您使用动态片段时会发生这种情况,并且在布局中使用片段标记来显示片段。而是使用布局(最好是FrameLayout)。假设您使用的是支持片段库。

值得一试。


0
2018-06-29 16:10