Android Fragments 为什么片段的onCreate()有时会先于活动的onCreate()调用?

bq9c1y66  于 2022-12-29  发布在  Android
关注(0)|答案(6)|浏览(216)

最近我遇到了一个很难重现的问题。当一个片段试图用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);
}

调用default getCount() 方法时,***AccountAdapter***内发生NPE。原因是***mAccounts***为空。此问题很少出现,我无法重现。
什么时候可以在活动的 onCreate() 之前调用片段的 onCreate()?根据源代码,片段的 onCreate() 在活动的 onCreate() 中调度。为什么在活动的onCreate()完成执行之后才调用它?

qq24tv8q

qq24tv8q1#

Activities回调不会在片段之后调用;在“活动”期间调用“片段”。
Activity.onCreate()中调用super.onCreate()之前初始化mAccounts

2sbarzqh

2sbarzqh2#

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

sz81bmfz

sz81bmfz3#

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

3phpmpom

3phpmpom4#

最近遇到了这个问题。请参见底部的堆栈跟踪。
正如FunkTheMonk所说,崩溃是由于Activity中的自定义onCreate()代码(紧接着super.onCreate())在Fragment中的自定义onCreate()代码(紧接着super.onCreate())之后执行
如果您确实需要在整个活动的onCreate()之后有希望地执行回调,请将代码片段放在onViewCreated(因为onActivityCreated()已弃用)而不是onCreate()
否则,当您的内存不足并且活动被回收时,就会发生上述情况。
根据我的经验,当我的MyActivity发送Intent时,一旦我按下back键返回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)
f87krz0w

f87krz0w5#

我可能回答得太晚了,但我还是在几天前遇到了这个问题。当你使用动态片段,并且在布局中使用片段标签来显示片段时,就会发生这种情况。相反,使用布局(最好是FrameLayout)。假设你使用的是支持片段库。
值得一试。

0sgqnhkj

0sgqnhkj6#

正如许多人所说,在XML中使用<fragment/>标记时会发生这种情况。我最初将其用于导航组件,但后来Android Studio建议将其更改为<androidx.fragment.app.FragmentContainerView/>
应用变更后,首先调用变更活动,然后调用片段。

相关问题