这个问题与以下内容有一些相似之处:
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 ]
我也不明白。这是因为此时视图还没有完全创建吗?
所以我的主要问题仍然存在。片段何时实际重新创建其实例,为什么它会调用生命周期方法,即使它不关心结果,是否有任何方法可以在第一次创建片段时不设置实例变量来检测它?
答案 0 :(得分:2)
当Fragment
分离ViewPager
时,它们将经历关闭生命周期(onPause()
,onSaveInstanceState()
,onStop()
,{{ 1}},onDestroyView()
等。)
但是,onDetach()
(更具体地说是ViewPager
)将通过并手动将片段的状态保存到其自己保存的状态(分离片段时调用FragmentStatePagerAdapter
)。这可能就是为什么覆盖调用FragmentManager.saveFragmentInstanceState(fragment)
的方法不会影响它。
您的视图更改被覆盖的原因是因为super.*(null)
发生在onCreateView()
之前,此时它将恢复已保存的状态并覆盖您的更改。你真的不应该在那个方法中设置你的视图状态 - 只需返回视图。
如果您确实想知道这是否是第一次创建片段,则只需检查onViewStateRestored()
即可。如果是这样,那是第一次发布。否则,它会从已保存的状态重新创建。