【问题标题】:How to restore fragment back stack with in an activity (After application is killed in background)如何在活动中恢复片段回栈(在后台杀死应用程序后)
【发布时间】:2016-02-19 04:25:15
【问题描述】:

在 Android 应用中-

假设我在一个 Activity - MyActivity 中,它一次拥有一个 Fragment

首先我将 Fragment A 加载到它(没有标签我将它添加到 FragmentManager 的后堆栈)

然后在某个时候我加载了 Fragment B(同样没有标签,我将它添加到 FragmentManager 的后堆栈)

然后在某个时候我加载了 Fragment C(同样没有标签,我将它添加到 FragmentManager 的后堆栈)

我正在使用popBackStack() 来启用后退按钮 行为,所以每当我从Fragment C 按下返回时,流程就像:

Fragment C -> Fragment B -> Fragment A -> 关闭MyActivity..

一切都很完美:-)

但是,如果我在 Fragment C 并且应用程序在后台被杀死(我使用了“设置”中的“不保留活动标志”)

并且重新上线 片段C已加载到MyActivity

但是FragmentManager的后栈只包含Fragment C..

后退按钮搞砸了

Fragment C -> 关闭 MyActivity..

为什么会这样?

如何在Activity 中正确恢复FragmentManager 的后台堆栈?

【问题讨论】:

  • 这可能是因为您的活动已被终止,并且如果您愿意,它会丢失所有引用如果是,则返回堆栈,然后删除(并从您的返回堆栈中删除)如果您的活动返回堆栈不满足,则按照您的偏好进行
  • @VishalMokal 感谢您的意见。活动的后台堆栈由片段管理器管理。这意味着有不止一种方法可以将片段添加或删除到后堆栈。此外,这种解决方案不会扩展到更大的应用程序。由于我还依赖于导航片段,因此首选更基本的解决方案。
  • “我正在使用 popBackStack 启用后退按钮行为”是什么意思?如果您使用 fragmentTransaction.begin().add(fragment).addToBackStack().commit() 添加片段,Android系统是否不会自动管理返回按钮行为?
  • 发布一些关于如何添加片段以及如何删除片段的代码(例如,您有 onBackPressed 方法吗?)
  • 你好,你能把你的代码放在这里吗..?

标签: android android-fragments fragmentmanager


【解决方案1】:

尝试在您的根活动上使用alwaysRetainTaskState。 Android 会自动清除 Activity backstack,因为它假定您已经很长时间没有使用该应用并且用户希望从头开始。

 <activity android:alwaysRetainTaskState="true"/>

此设置将阻止该行为,并且该行为可能会被片段管理器继承。

【讨论】:

  • 此标志仅适用于活动级别
  • 不工作,当应用被杀死并使用通知打开时,backstack仍然会变空。
【解决方案2】:

在开发您的应用程序时,我建议您使用 ADB 测试活动、片段的恢复/保存状态:

  1. 打开应用
  2. 在活动之间导航
  3. 新闻主页
  4. ADB -> 终止(停止)应用程序
  5. 按下应用程序堆栈(设备上的菜单按钮)并恢复应用程序

这样您就可以调试保存/恢复状态。

如果你没有复杂的应用,我建议你在activity中处理保存/恢复状态:

private Fragment1 mFragment;

@Override
protected void onCreate(Bundle savedState) {
   super.onCreate(savedState);
   // ...

   if (savedState == null) {
       mFragment = new Fragment1();

       getFragmentManger().beginTransacation().add(mFragment, TAG).addToBackStack(TAG).commit();
   }
   else {
       mFragment = getFragmentMananager().findFragmentByTag(TAG);
   }
}

如果您有多个FragmentsViewPager 或嵌套片段,那么事情会变得非常复杂。我建议你重新启动整个应用程序:

@Override
protected void onCreate(Bundle savedState) {
   super.onCreate(savedState);

   if (savedState != null) {
      Intent intent = new Intent(ActivityMain.this, ActivityMain.class);
      intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
      startActivity(intent);

      return;
   }
}

如果你想处理每个保存/恢复状态,请阅读这篇文章:http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html

【讨论】:

  • 我同意,如果您的根活动是托管片段的活动,则第二种解决方案(重新启动活动)是一种快速解决方案,谢谢
【解决方案3】:

试试这个方法

public void setRetainInstance (boolean retain)

控制是否在重新创建 Activity 时保留片段实例(例如来自配置更改)。这只能与不在后台堆栈中的片段一起使用。如果设置,则在重新创建活动时片段生命周期将略有不同:

来自开发者网站 http://developer.android.com/reference/android/app/Fragment.html#setRetainInstance%28boolean%29

【讨论】:

    【解决方案4】:

    在您的应用程序终止后,永远不应加载片段 C。您的应用程序中有 Init 片段吗?理想情况下,当您实现一个片段的弹出时,应该有一个 Init 屏幕。如果应用程序因内存原因死亡或被终止,则应用程序应从 Fragment A(Init Fragment)开始。不是来自片段 C。

    如果您的问题需要这个解决方案,那么当有新片段出现时,您应该持久保存每个片段。理想情况下,这意味着您将后台堆栈保存在首选项或数据库中以实现此目的。

    【讨论】:

    • Super.onCreate 将在重新创建 Activity 时加载最后一个片段。数据丢失也得到管理。关注的是片段的顺序
    • 你是否将 savedInstance 的对象传递给 onCreate ?
    • 是的,我也一样
    • 如果片段 C 自动加载,此信息将保存在实例中。您应该使用 onSaveInstanceState() 和 onRestoreInstanceState()。你可能会在这里得到一个关于它的填充描述:developer.android.com/training/basics/activity-lifecycle/…你应该重写 onSaveInstanceState() 并在你的活动再次开始时恢复它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-15
    相关资源
    最近更新 更多