【问题标题】:Why Fragment's onCreate() is sometimes called prior to Activity's onCreate()?为什么 Fragment 的 onCreate() 有时会在 Activity 的 onCreate() 之前调用?
【发布时间】:2015-07-29 15:34:56
【问题描述】:

最近我遇到了一个难以重现的问题。 NPE 在片段尝试使用来自 Activity 的数据初始化 ArrayAdapter 时发生。 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);
}

当调用默认的 getCount() 方法时,NPE 发生在 AccountAdapter 内。原因是 mAccounts 为空。 这个问题很少出现,我无法重现它。

fragment 的 onCreate() 何时可能在活动的 onCreate() 之前被调用? 根据源码,Fragment的onCreate()是在Activity的onCreate()中调度的。为什么 Activity 的 onCreate() 执行完之后才调用呢?

【问题讨论】:

  • 不,这是不可能的。
  • 你应该发布更多关于你的片段如何在你的活动中显示的代码。
  • 我同意@Ilya Vorobiev。当调用活动的 super.onCreate() 时,会分派 Fragment 的 onCreate()。问题是为什么在大多数情况下它是在 Activity 的 onCreate 之后执行的。

标签: android android-fragments android-lifecycle


【解决方案1】:

在 Fragments 之后不调用活动回调; Fragment 在 Activity 期间被调用。

Activity.onCreate() 中调用super.onCreate() 之前初始化mAccounts

【讨论】:

  • 感谢您的提示。肯定有几种方法可以解决这个问题。问题是为什么行为不同。 onCreate() 是如何准确触发的以及为什么它有时会在活动的 onCreate() 之后发生。
【解决方案2】:

您的片段的onCreate() 可以在您的活动的onCreate() 方法完成之前调用。您的片段中有onActivityCreated() 回调和onCreateView()。您可以使用其中任何一个 - 它在 onCreate 活动方法之后执行。

【讨论】:

  • 你知道具体情况吗?正如我所提到的,这个问题很少被复制。
  • 出现这个问题的情况很多。如果您查看 FragmentActivity 的 onCreate() 方法,您会看到该活动首先将自身附加到 Fragment,然后执行 super.onCreate()。所以不能保证你的代码会在你的片段的 onCreate() 之前执行。
  • 好吧,当问题 100% 可重现时,我会理解它,因为确实在活动的 onCreate() 之前调用了我的片段的 onCreate()。我想我应该编辑这个问题。应该颠倒过来。为什么 Fragment 的 onCreate() 在 Activity 的 onCreate() 之后被调用,即使它是在 Activty 的 onCreate() 中调度的。
  • 通常在由于活动重新创建而恢复片段时发生。当您第一次初始化活动时,您手动创建片段(在 super.onCreate() 之后),但是当重新创建活动时,片段会在 super.onCreate() 中的某些代码中重新创建。
【解决方案3】:

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

【讨论】:

    【解决方案4】:

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

    正如 FunkTheMonk 所说,崩溃是由于您的 Activity 中自定义的 onCreate() 代码(就在 super.onCreate() 之后)在您的 Fragment 中的自定义 onCreate() 代码之后执行(就在 super .onCreate())

    如果您确实需要在整个 Activity 的 onCreate() 之后执行您的回调,请将您的代码片段放入 onActivityCreated() 而不是 onCreate()

    否则当你的内存不足,Activity被回收时,就会出现上述情况。

    根据我的经验,当我的 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)。假设您使用的是支持片段库。

      值得一试。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-06-16
        • 2012-12-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-20
        相关资源
        最近更新 更多