嵌套片段在方向更改时创建两次

Nested fragments created twice on orientation change

我创建此示例是为了了解 android 片段在屏幕方向更改时的生命周期。

MainActivity 是 DrawerLayout 的容器,DrawerLayout 允许您选择一个 fragment,它将填充 MainActivity 屏幕。

public class MainActivity extends ActionBarActivity {
...
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Log.d("MainActivity", "onCreate savedInstanceState = "+(savedInstanceState == null ? "null" : "not null"));

...
    mDrawerList.setOnItemClickListener(new AdapterView.OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

    if (position == 0) {
            if (viewingPosition == position) {
                mDrawerLayout.closeDrawer(mDrawerList);
                return;
            }
            getSupportFragmentManager()
                    .beginTransaction()
                    .replace(R.id.contentFrame, new ParentPagerFragment(),
                                ParentPagerFragment.TAG).commit();
           viewingPosition = 0;

    }

    if (position == 1) {
            if (viewingPosition == position) {
                mDrawerLayout.closeDrawer(mDrawerList);
                return;
            }
            getSupportFragmentManager().beginTransaction()
                .replace(R.id.contentFrame, ChildTextViewFragment.newInstance("hello fragment"), ChildTextViewFragment.TAG)
                .commit();
            viewingPosition = 1;
    }
}
...

getSupportFragmentManager()
            .beginTransaction()
            .replace(R.id.contentFrame, new ParentPagerFragment(),
                    ParentPagerFragment.TAG).commit();
...

然后我有 ParentPagerFragment,ParentPagerFragment 只包含一个 ViewPager 和 3 个 ChildTextViewFragment。

public class ParentPagerFragment extends Fragment {
...

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    Log.d(TAG, "onCreateView savedInstanceState is "+(savedInstanceState == null ? "null" : "not null"));

    View v = inflater.inflate(R.layout.fragment_pager, container, false);

    List<ChildTextViewFragment> viewFragments = new ArrayList<>();
    viewFragments.add(ChildTextViewFragment.newInstance("Fragment1"));
    viewFragments.add(ChildTextViewFragment.newInstance("Fragment2"));
    viewFragments.add(ChildTextViewFragment.newInstance("Fragment3"));

    MyPagerAdapter mPagerAdapter = new MyPagerAdapter(getChildFragmentManager(), viewFragments);

    ViewPager mViewPager = (ViewPager) v.findViewById(R.id.pager);
    mViewPager.setAdapter(mPagerAdapter);

    return v;
}

...
}


class MyPagerAdapter extends FragmentPagerAdapter {

    List<ChildTextViewFragment> viewFragments;

    public MyPagerAdapter(FragmentManager fm, List<ChildTextViewFragment> viewFragments) {
        super(fm);
        this.viewFragments = viewFragments;
    }

    @Override
    public Fragment getItem(int index) {
        return viewFragments.get(index);

    }

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

    @Override
    public CharSequence getPageTitle(int position){
        if(position == 0) {
            return "Fragment1";
        } else if (position == 1) {
            return "Fragment2";
        } else {
            return "Fragment3";
        }
    }

}

ChildTextViewFragment 仅用于显示一些文本

public class ChildTextViewFragment extends Fragment {
...

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    View view = inflater.inflate(R.layout.fragment_text, container, false);

    TextView mTextView = (TextView) view.findViewById(R.id.textView1);
    String text = getArguments().getString(TEXT_KEY);
    mTextView.setText(text);

    Log.d(TAG, text+" :: onCreateView savedInstanceState is " + (savedInstanceState == null ? "null" : "not null"));

    return view;

}

在我第一次 运行 这个例子后,我按预期收到了这些日志消息:

06-01 10:34:24.154: D/MainActivity(8426): onCreate savedInstanceState = null
06-01 10:34:24.272: D/ParentPagerFragment(8426): onCreateView savedInstanceState is null
06-01 10:34:24.389: D/ChildTextViewFragment(8426): Fragment1 :: onCreateView savedInstanceState is null
06-01 10:34:24.390: D/ChildTextViewFragment(8426): Fragment2 :: onCreateView savedInstanceState is null

当我旋转显示器时,惊喜出现了:

06-01 10:36:15.697: D/MainActivity(8426): onCreate savedInstanceState = not null
06-01 10:36:15.713: D/ParentPagerFragment(8426): onCreateView savedInstanceState is not null
06-01 10:36:15.716: D/ChildTextViewFragment(8426): Fragment1 :: onCreateView savedInstanceState is not null
06-01 10:36:15.717: D/ChildTextViewFragment(8426): Fragment2 :: onCreateView savedInstanceState is not null

06-01 10:36:15.718: D/ParentPagerFragment(8426): onCreateView savedInstanceState is null
06-01 10:36:15.739: D/ChildTextViewFragment(8426): Fragment1 :: onCreateView savedInstanceState is null
06-01 10:36:15.740: D/ChildTextViewFragment(8426): Fragment2 :: onCreateView savedInstanceState is null

我原以为所有的片段都会被恢复并再次显示(就像这个日志的前 4 行显示的那样),但我不明白,为什么所有的片段都用 savedInstanceState = null 再次创建?这是一种常见行为,还是我做错了什么?

您正在使用 FragmentPagerAdapter 。因此,默认情况下,它会尝试在您的 viewpager 中一次加载两个索引的两个片段。

所以你需要提到 pager.offScreenPageLimit(0) 来加载它一次。

尝试在 MainActivity 中为 savedInstanceState 添加 null 检查 onCreate(Bundle savedInstanceState)这样的方法

        if (savedInstanceState == null) {
             getSupportFragmentManager()
            .beginTransaction()
            .replace(R.id.contentFrame, new ParentPagerFragment(),
                    ParentPagerFragment.TAG).commit();
        }