viewPager如何在方向更改时保留片段状态?

时间:2015-01-31 17:58:56

标签: android android-fragments android-viewpager android-lifecycle android-orientation

这个问题与以下内容有一些相似之处:

Fragment in ViewPager on Fragment doesn't reload on orientation change

但不同之处在于,我想知道片段状态是如何实际保留的,因为我观察到很多奇怪的事情发生。

我的观察如下:

使用FragmentPagerAdapter设置ViewPager:

  class HomeAdapter extends FragmentPagerAdapter
{
    HomeAdapter(FragmentManager manager)
    {
        super(manager);
    }

    @Override
    public Fragment getItem(int i) {
        try {
            return (Fragment) mTabs.get(i).getFragmentClass().newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return mTabs.get(position).getTitle();
    }

    @Override
    public int getCount() {
        return mTabs.size();
    }
}

在我的活动中onCreate我打电话:

setContentView(R.layout.activity_home);
    mTabs = new ArrayList<>();
    mTabs.add(new SlidingTabItem("A", FragmentA.class));
    mTabs.add(new SlidingTabItem("B", FragmentB.class));

    mViewPager = (ViewPager) findViewById(R.id.viewpager);
    mViewPager.setAdapter(new HomeAdapter(getSupportFragmentManager()));

    mSlidingTabLayout = (SlidingTabLayout) findViewById(R.id.sliding_tabs);
    mSlidingTabLayout.setViewPager(mViewPager);

现在,当设备方向发生变化时,viewPager会在片段内的editText字段中重新创建所有内容。

澄清这实际上是我想要的行为,但我不明白。

我检查了viewPager和FragmentPagerAdapter的来源。我发现FragmentPagerAdapter会搜索FragmentManager,如果该位置的片段已经存在。如果是,则调用FragmentTransaction.attach()重新附加它。

它还使用FragmentManager.detach()

来解除片段

据我了解,这会在FragmentManager中保留FragmentState。然而,WHERE和WHEN确实可以恢复。

我尝试在我的片段中连接到包含savedInstanceState的每个生命周期方法,并使用null作为savedInstanceState调用super.X,但视图仍将以相同的方式恢复。

恢复的片段似乎也忽略了对onCreateView中完成的视图的更改。我尝试了以下方法:

mMajor = (EditText) contentView.findViewById(R.id.major);
mMajor.setText("123");

在第一次创建片段时起作用。然而,即使onCreateView实际上第二次被调用,这个指令显然没有做任何事情,因为主要的editText没有重置为“123”。

有趣的是,调用mMajor.getText()。toString()会返回类似于:

的内容
[ 01-31 18:29:54.634 18540:29583 I/ActivityManager ]
我也不明白。这是因为此时视图还没有完全创建吗?

所以我的主要问题仍然存在。片段何时实际重新创建其实例,为什么它会调用生命周期方法,即使它不关心结果,是否有任何方法可以在第一次创建片段时不设置实例变量来检测它?

1 个答案:

答案 0 :(得分:2)

Fragment分离ViewPager时,它们将经历关闭生命周期(onPause()onSaveInstanceState()onStop(),{{ 1}},onDestroyView()等。)

但是,onDetach()(更具体地说是ViewPager)将通过并手动将片段的状态保存到其自己保存的状态(分离片段时调用FragmentStatePagerAdapter)。这可能就是为什么覆盖调用FragmentManager.saveFragmentInstanceState(fragment)的方法不会影响它。

您的视图更改被覆盖的原因是因为super.*(null)发生在onCreateView()之前,此时它将恢复已保存的状态并覆盖您的更改。你真的不应该在那个方法中设置你的视图状态 - 只需返回视图。

如果您确实想知道这是否是第一次创建片段,则只需检查onViewStateRestored()即可。如果是这样,那是第一次发布。否则,它会从已保存的状态重新创建。