【问题标题】:Saving states of multiple fragments in activity在活动中保存多个片段的状态
【发布时间】:2017-05-27 15:13:41
【问题描述】:

我正在开发一个应用程序,但有一件具体的事情困扰着我。假设我有一个活动和两个片段。FragmentA 和 FragmentB 和 FragmentA 在活动开始时附加。

我想在方向发生变化时保存片段数据和片段状态。我已经使用OnSavedInstanceState方法成功保存了片段数据。现在我想在活动中保存片段状态,以便如果发生方向更改,我希望位于我所在的片段上(在我的情况下,FragmentA 或 FragmentB 取决于在配置更改发生之前显示的内容)。

这就是我在 Activity 中保存片段状态的方式:

 @Override
protected void onSaveInstanceState(Bundle outState) {
    // Save the values you need into "outState"
    super.onSaveInstanceState(outState);
    outState.putLong(SS_DATE, userDate.getTime());

    android.support.v4.app.FragmentManager manager = getSupportFragmentManager();
    Fragment currentFragment = this.getSupportFragmentManager().findFragmentById(R.id.content_container);
    manager.putFragment(outState, "currentFragment", currentFragment);
}

这就是我在方向改变发生时检索我所在的片段的方式:

  @Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);

    FragmentManager manager = getSupportFragmentManager();
    @SuppressLint("CommitTransaction")
    FragmentTransaction transaction = manager.beginTransaction();

    if (savedInstanceState != null) {
        Fragment MyFragment = (Fragment) manager.getFragment(savedInstanceState, "currentFragment");

        if (MyFragment instanceof FragListStudentsAttendance) {
            Log.v("onRestore", FragListStudentsAttendance.TAG);


        }else if (MyFragment instanceof FragGetClassesForAttendance){
            Log.v("onRestore", FragGetClassesForAttendance.TAG);
            if(MyFragment!=null) {
                mFragGetClassesForAttendance = (FragGetClassesForAttendance) MyFragment;
            }else{


     mFragGetClassesForAttendance = new FragGetClassesForAttendance();
            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
//            mFragGetClassesForAttendanceNew.setRetainInstance(true);
//            transaction.replace(R.id.content_ssadmin_container, mFragGetClassesForAttendanceNew, "FragGetClassesForAttendance").addToBackStack(null);
            transaction.add(R.id.content_ssadmin_container, mFragGetClassesForAttendance, FragGetClassesForAttendance.TAG);
            //transaction.replace(R.id.newEnrollmentMainContainer, mFragNewEnrollmentResults).addToBackStack("FragNewEnrollments");
            transaction.commit();
            mFragGetClassesForAttendance.setDate(userDate);
            }
        }
    }

}

现在 场景 1: 如果我在片段 A 上并且我旋转设备,那么一切都可以正常工作。像片段一样有将数据加载到列表视图中的 Web 服务,所以我检查数据是否存在,然后不需要运行 Web 服务并且现在可以工作

场景 2: 如果我在片段 B 上并且方向发生变化,一切正常,因为它应该在片段 B 上。现在,当我按下 后退按钮时,再次调用片段 A,所有数据也来自服务。我认为这不应该发生,因为它应该在 BackStack 中并且它的数据已保存。那么我现在应该在这里做什么?

场景 3: 在 FragmentB 上,我注意到当我旋转设备时,也会调用 FragmentA 的 saveInstanceState 函数。为什么会这样?我在哪里用 FragmentA 替换 FragmentB ?

一些困惑:

让我也谈谈一些困惑,尽管我已经搜索并阅读了很多关于片段和活动生命周期的内容,但也许有人会向我解释清楚, 实际上,我想在设备旋转时保存每个活动和片段的数据。我知道如何使用活动(如何保存状态)来做到这一点,所以我也知道如何在片段中做到这一点(保存片段视图的状态)现在我很困惑如何告诉活动显示哪个片段以及在配置之后去哪个变化(旋转)?如果我在 FragmentB 上,FragmentA 会发生什么情况?它会在后台一次又一次地连接和分离吗?

【问题讨论】:

  • @ShaartiKAKA 我已经看到了这个链接,但我仍然遇到同样的问题。当我在第二个或说第三个片段时,片段状态不会保存。
  • 此时片段没有保存其状态
  • 正如我所说,当我在第二个片段上并回到第一个片段时,它会重新创建,但理想情况下它不应该。
  • 它将从后台堆栈重新创建

标签: android android-fragments fragment savestate fragment-lifecycle


【解决方案1】:

我得到了你的问题和困惑。我认为片段的生命周期让你感到困惑。它确实会让你感到困惑。

你需要学习不同的情况。 1. Fragment 处于前台时的生命周期(随活动附着和分离)。请仔细观察所有将调用的方法,即 OnSaveInstance、onCreateView、OnDestroyView、onDestroy 2. Fragment 处于后台时的生命周期(遵守上述方法) 3. Fragment 被添加到后台(而不是前台)时的生命周期

我很确定你对第 3 点感到困惑。当片段被添加到 backstack 时,它永远不会被破坏。所以旋转设备两次会将碎片数据设置为空。我认为您正在恢复 ActivityCreated 或 onViewCreated 上的数据,

我建议您在 oncreate 中恢复片段数据。当您的片段从后台返回到前台时,这对您有用。

例子

    private List<String> mCountries;</pre>
@Override
public void onCreate(Bundle savedInstanceState)
{
    if (savedInstanceState != null)
    {
        // Populate countries from bundle
    }
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
    View view = inflater.inflate(R.layout.fragment_countries, container, false);

    if (mCountries == null)
    {
        // Populate countries by calling AsyncTask
    }

    return view;
}

public void onSaveInstanceState(Bundle outState)
{
    // Save countries into bundle
}

希望这能消除您的困惑。

【讨论】:

  • 是的,第 3 点最令人困惑,我开发了一个虚拟应用程序来检查活动中片段的状态和生命周期,因此根据您的情况,当活动在 backStack 中时,它被称为 backStack在以下方式这样: MyFragment:onCreatedView:调用 MyFragment:onViewCreated:调用 MyFragment:onActivityCreated:调用 MyFragment:onStart:调用 MyFragment:onResume:调用 SecondFragment:onPause:调用 SecondFragment:onStop:调用 SecondFragment:onDestroyView:调用 SecondFragment:onDestroy:调用SecondFragment:onDetach:调用
  • 是的,但是您可能会看到,通过将第一个片段添加到后台堆栈中,它的 onDestroy 永远不会被调用,因此它不会被销毁。
  • 啊是的。我应该在发布这个问题之前先尝试一下:P 但感谢您的帮助
  • 如果对您有帮助,请将其标记为选定答案。这样任何陷入这种情况的人都可以得到这个答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多