You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android横竖屏切换时如何避免同一个Fragment创建两个实例

问题根因

  • 屏幕旋转触发Activity重建时,系统会自动恢复所有之前添加到FragmentManager中的Fragment实例,包括之前由ViewPager2创建的FragmentB
  • 原有代码存在两处重复创建FragmentB的逻辑:
    1. 横屏场景下手动调用new FragmentB()加载到右侧FrameLayout
    2. ViewPager2的FragmentStateAdapter的createFragment方法每次position=1时都返回新的FragmentB实例
  • 额外笔误:原有onCreateView中第二个条件判断依然是isLandScape(),属于逻辑错误。

修复方案(复用FragmentB实例,无重复创建)

步骤1:修改MasterFragment逻辑,统一管理FragmentB实例

public class MasterFragment extends Fragment
{
    NewPagerAdapter mSectionsPagerAdapter;
    ViewPager2 mViewPager;
    boolean mSplitView;
    // 新增:全局持有唯一的FragmentB实例
    private FragmentB mFragmentB;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 优先从FragmentManager中恢复已存在的FragmentB,不存在才新建
        Fragment existingB = getChildFragmentManager().findFragmentByTag(FragmentB.TAG);
        if (existingB instanceof FragmentB) {
            mFragmentB = (FragmentB) existingB;
        } else {
            mFragmentB = new FragmentB();
        }
    }

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
    {
        View view = inflater.inflate(R.layout.masterfragment, container, false);
        mSplitView = isLandScape();

        // 先把FragmentB从原有容器中移除,避免重复添加报错
        if (mFragmentB.isAdded()) {
            getChildFragmentManager().beginTransaction().remove(mFragmentB).commitNow();
        }

        if (mSplitView)
        {
            // 横屏:把FragmentB添加到右侧FrameLayout
            getChildFragmentManager().beginTransaction().add(R.id.container, mFragmentB, FragmentB.TAG).commitNow();
        }

        mViewPager = view.findViewById(R.id.pager);
        mSectionsPagerAdapter = new NewPagerAdapter(getChildFragmentManager(), getLifecycle());
        mViewPager.setOffscreenPageLimit(2); // 不需要7,2足够覆盖两个页面
        mViewPager.setAdapter(mSectionsPagerAdapter);

        // 竖屏场景下如果之前在FragmentB页面,切换后保持显示
        if (!mSplitView && savedInstanceState != null) {
            int lastPage = savedInstanceState.getInt("last_pager_position", 0);
            mViewPager.setCurrentItem(lastPage);
        }

        return view;
    }

    // 新增:保存ViewPager当前位置,横竖屏切换后恢复
    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        if (mViewPager != null) {
            outState.putInt("last_pager_position", mViewPager.getCurrentItem());
        }
    }

    public boolean isLandScape()
    {
        int orientation = getResources().getConfiguration().orientation;
        return orientation == Configuration.ORIENTATION_LANDSCAPE;
    }

    public boolean backOnePage()
    {
        if(mViewPager == null || mSplitView)
            return false;

        int page = mViewPager.getCurrentItem();
        if(page > 0)
        {
            mViewPager.setCurrentItem(page - 1);
            return true;
        }
        return false;
    }

    public void viewFragmentB()
    {
        if(!mSplitView)
            mViewPager.setCurrentItem(1);
    }

    public class NewPagerAdapter extends FragmentStateAdapter
    {
        public NewPagerAdapter(@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle)
        {
            super(fragmentManager, lifecycle);
        }

        @NonNull
        @Override
        public Fragment createFragment(int position)
        {
            if(position == 0)
                return new FragmentA();
            // 直接返回全局唯一的FragmentB实例,不新建
            return mFragmentB;
        }

        @Override
        public int getItemCount()
        {
            return mSplitView ? 1 : 2;
        }
    }
}

步骤2:删除原有冗余逻辑

原有onCreateView里的第二个else if (isLandScape())逻辑完全冗余且错误,直接删除即可,因为横竖屏对应的layout文件本身已经做了区分,不需要动态移除View。

验证效果

修改后旋转屏幕,FragmentB的COUNTER值只会在首次创建时+1,旋转时不会重复增加,不会出现同时两个实例的情况,地图页面状态也能完全复用不需要重新加载。

内容的提问来源于stack exchange,提问作者user3115340

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 01:45:02