【问题标题】:How does viewPager retain fragment states on orientation change?viewPager 如何在方向改变时保留片段状态?
【发布时间】:2015-01-31 17:58:56
【问题描述】:

这个问题有一些相似之处:

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 的来源。我发现如果该位置的 Fragment 已经存在,FragmentPagerAdapter 会搜索 FragmentManager。如果是,它会调用 FragmentTransaction.attach() 重新附加它。

它还使用 FragmentManager.detach() 分离 Fragment

据我了解,这保留了 FragmentManager 中的 FragmentState。然而,这实际上是在何时何地恢复的。

我尝试挂钩到我的片段中的每个生命周期方法,其中包含一个 savedInstanceState 并调用 super.X 并使用 null 作为 savedInstanceState 但是视图仍然会以相同的方式恢复。

恢复的片段似乎也忽略了 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 ]

我也不明白。这是因为此时视图尚未完全创建吗?

所以我的主要问题仍然存在。片段何时真正重新创建它的实例,为什么它调用生命周期方法,即使它不关心结果,有没有办法在第一个片段创建时不设置实例变量的情况下检测到这一点?

【问题讨论】:

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


    【解决方案1】:

    Fragments 被ViewPager 分离时,它们将经历关闭生命周期(onPause()onSaveInstanceState()onStop()onDestroyView()onDetach() 等)

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

    您的视图更改被覆盖的原因是onCreateView() 发生在onViewStateRestored() 之前,此时它将恢复保存的状态并覆盖您的更改。无论如何,您真的不应该在该方法中设置您的视图状态 - 只需返回视图。

    如果您确实想知道是否是第一次创建片段,检查if (savedInstanceState == null) 就足够了。如果是这样,这是第一次发射。否则,它会从保存状态重新创建自己。

    【讨论】:

      猜你喜欢
      • 2015-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多