Back Stack 未维护 - 如何防止 Fragment 被破坏?

Posted

技术标签:

【中文标题】Back Stack 未维护 - 如何防止 Fragment 被破坏?【英文标题】:Back Stack is not maintained - How to prevent fragment from being destroyed? 【发布时间】:2017-12-25 14:01:31 【问题描述】:

我有 2 个活动都从 AppCompatActivity 扩展如下

MainActivity - 托管通过FragmentPagerAdapter附加的3个片段

AboutActivity - 独立活动,不使用片段

问题 : MainActivity 加载完所有 3 个 Fragment 后,用户从 MainActivity 的 optionMenu 中打开 About Activity。在 AboutActivity 中,用户单击 Toolbar 后退按钮,再次返回 MainActivity。

这就是问题所在,MainActivity 中的所有片段都与 Activity 本身一起被销毁,并且它们被重新创建。

我已经捕获了以上 3 个步骤的日志,并在下面复制。

我在 *** 上找到了similar question,但没有发现它相关,因为我使用的是 FragmentPagerAdapter,而这个问题是基于片段事务的

日志 - App Started 和 MainActivity 加载了 3 个 Fragment,List Fragment 显示了 3 次,因为 ListFragment 继承了 3 个 Fragment。根据下面的日志应用程序行为似乎很好。

    I/System.out: MainActivity.onAttachFragment ReportFragment2a7b515 #0 android.arch.lifecycle.LifecycleDispatcher.report_fragment_tag
    I/System.out: MainActivity.onCreate
    I/System.out: MainFragmentPageAdapter.MainFragmentPageAdapter
    I/System.out: MainActivity.onStart
    I/System.out: MainActivity.onResume
    I/System.out: MainActivity.onResumeFragments
    I/System.out: MainFragmentPageAdapter.getItem
    I/System.out: MainFragmentPageAdapter.getItem
    I/System.out: MainFragmentPageAdapter.getItem
    I/System.out: ListFragment.onAttach context = com.global.MainActivity@99b50ff, activity = com.global.MainActivity@99b50ff
    I/System.out: MainActivity.onAttachFragment ListFragment894a792 #0 id=0x7f0901a3 android:switcher:2131296675:0
    I/System.out: ListFragment.onCreate
    I/System.out: ListFragment.onAttach context = com.global.MainActivity@99b50ff, activity = com.global.MainActivity@99b50ff
    I/System.out: MainActivity.onAttachFragment ListFragment720b78c #1 id=0x7f0901a3 android:switcher:2131296675:1
    I/System.out: ListFragment.onCreate
    I/System.out: ListFragment.onAttach context = com.global.MainActivity@99b50ff, activity = com.global.MainActivity@99b50ff
    I/System.out: MainActivity.onAttachFragment ListFragmentfe7c078 #2 id=0x7f0901a3 android:switcher:2131296675:2
    I/System.out: ListFragment.onCreate
    I/System.out: ListFragment.onCreateView
    I/System.out: ListFragment.onViewStateRestored
    I/System.out: ListFragment.onStart
    I/System.out: ListFragment.onResume
    I/System.out: ListFragment.onCreateView
    I/System.out: ListFragment.onViewStateRestored
    I/System.out: ListFragment.onCreateView
    I/System.out: ListFragment.onViewStateRestored
    I/System.out: ListFragment.onStart
    I/System.out: ListFragment.onResume
    I/System.out: ListFragment.onStart
    I/System.out: ListFragment.onResume

用户从选项菜单中选择关于,并且关于活动已启动,此活动不使用任何片段。根据下面的日志,应用行为似乎很好。

    I/System.out: ListFragment.onPause
    I/System.out: ListFragment.onPause
    I/System.out: ListFragment.onPause
    I/System.out: MainActivity.onPause
    I/System.out: AboutActivity.onAttachFragment ReportFragment9b431e0 #0 android.arch.lifecycle.LifecycleDispatcher.report_fragment_tag
    I/System.out: AboutActivity.onCreate
    I/System.out: AboutActivity.onStart
    I/System.out: AboutActivity.onResume
    I/System.out: AboutActivity.onResumeFragments
    I/System.out: AboutActivity.onAttachedToWindow
    I/System.out: ListFragment.onSaveInstanceState
    I/System.out: ListFragment.onSaveInstanceState
    I/System.out: ListFragment.onSaveInstanceState
    I/System.out: ListFragment.onStop
    I/System.out: ListFragment.onStop
    I/System.out: ListFragment.onStop
    I/System.out: MainActivity.onStop

用户点击返回按钮,应该再次回到 MainActivity。它确实发生了,但在此之前 MainActivity 上的所有片段都被销毁,MainActivity 本身被销毁,并且片段和活动都被重新创建。 不确定是什么导致 MainActivity 及其下的 3 个片段被破坏和重新创建。 (这是我正在寻找解决方案的问题)

    I/System.out: AboutActivity.onPause
    I/System.out: ListFragment.onDestroy
    I/System.out: ListFragment.onDetach
    I/System.out: ListFragment.onDestroy
    I/System.out: ListFragment.onDetach
    I/System.out: ListFragment.onDestroy
    I/System.out: ListFragment.onDetach
    I/System.out: MainActivity.onDestroy
    I/System.out: MainActivity.onAttachFragment ReportFragmenta36b9c6 #0 android.arch.lifecycle.LifecycleDispatcher.report_fragment_tag
    I/System.out: MainActivity.onCreate
    I/System.out: MainFragmentPageAdapter.MainFragmentPageAdapter
    I/System.out: MainActivity.onStart
    I/System.out: MainActivity.onResume
    I/System.out: MainActivity.onResumeFragments
    I/System.out: MainFragmentPageAdapter.getItem
    I/System.out: MainFragmentPageAdapter.getItem
    I/System.out: MainFragmentPageAdapter.getItem
    I/System.out: ListFragment.onAttach context = com.global.MainActivity@4adb3a1, activity = com.global.MainActivity@4adb3a1
    I/System.out: MainActivity.onAttachFragment ListFragment7a21b5a #0 id=0x7f0901a3 android:switcher:2131296675:0
    I/System.out: ListFragment.onCreate
    I/System.out: ListFragment.onAttach context = com.global.MainActivity@4adb3a1, activity = com.global.MainActivity@4adb3a1
    I/System.out: MainActivity.onAttachFragment ListFragment5f7418b #1 id=0x7f0901a3 android:switcher:2131296675:1
    I/System.out: ListFragment.onCreate
    I/System.out: ListFragment.onAttach context = com.global.MainActivity@4adb3a1, activity = com.global.MainActivity@4adb3a1
    I/System.out: MainActivity.onAttachFragment ListFragmentcc17268 #2 id=0x7f0901a3 android:switcher:2131296675:2
    I/System.out: ListFragment.onCreate
    I/System.out: ListFragment.onCreateView
    I/System.out: ListFragment.onViewStateRestored
    I/System.out: ListFragment.onStart
    I/System.out: ListFragment.onResume
    I/System.out: ListFragment.onCreateView
    I/System.out: ListFragment.onViewStateRestored
    I/System.out: ListFragment.onCreateView
    I/System.out: ListFragment.onViewStateRestored
    I/System.out: ListFragment.onStart
    I/System.out: ListFragment.onResume
    I/System.out: ListFragment.onStart
    I/System.out: ListFragment.onResume
    I/System.out: AboutActivity.onStop
    I/System.out: AboutActivity.onDestroy
    I/System.out: AboutActivity.onDetachedFromWindow

【问题讨论】:

拜托,您能更具体地解释一下您的问题吗? 分享你创建片段的代码 @MeknessiHamida - 分享了代码、日志并更新了更多描述。 @TarlanAhad - 请立即查看 FragmentStatePagerAdapter 在片段数量有限时得到更好的支持。 【参考方案1】:

终于找到了解决办法

从 AndroidManifest 行 <activity android:name=".AboutActivity" android:label="About" android:configChanges="orientation|screenSize" /> 中删除了 android:parentActivityName=".MainActivity"

并处理工具栏后按如下。

@Override
public boolean onOptionsItemSelected(MenuItem item) 
   if (item.getItemId() == android.R.id.home)
   
      onBackPressed();
      return  true ;
   

return super.onOptionsItemSelected(item);

【讨论】:

接受您的回答,以便其他人在遇到您的问题时知道去哪里。 :) *** 不会让我在一天之前接受自我回答【参考方案2】:

由于您尚未共享代码。我认为可能有 3 种导航场景: 1.A(startActivity())--->B(startActivity())--->A 2.A(startActivity()+finish())-->B(startActivity())-->A 3.A(startActivity())--->B(finish() or onBackPressed())--->A 第一种情况和第二种情况,Activity A的新实例被创建,所以很明显fragment被销毁并重新创建。在第三种情况,Activity A的实例没有被销毁,因为它保存在backstack中。当 B 被销毁时,活动 A 刚刚从堆栈中弹出。在这种情况下,活动不会被破坏,因此片段也不会被破坏。 所以这取决于你如何导航到 A->B->A。如果你想防止 Fragment 被破坏,你必须切换到没有被破坏或在 backstack 上可用的 Activity A。

【讨论】:

以上是关于Back Stack 未维护 - 如何防止 Fragment 被破坏?的主要内容,如果未能解决你的问题,请参考以下文章

在调用新活动时从 Back Stack 中删除所有活动 [重复]

从类模板中排除类型

容器适配器————stack

如何防止回到之前的活动?

在back-stack中添加同一个fragment的多个实例,之前添加的实例的数据仍然存在

OAuth2.0 Server stack如何使用状态来防止CSRF?对于draft2.0 v20