应用被系统杀死后返回,BottomNavigationView无法切换Fragment
我之前也遇到过一模一样的问题,咱们来拆解下原因和修复方法:
问题原因
这个问题的核心在于Activity后台重建时,系统会自动恢复之前添加的Fragment,但这些恢复的Fragment是全新的实例,和你代码中初始化的成员变量不是同一个对象。
当你第一次启动Activity时,savedInstanceState为null,你创建了三个Fragment实例并添加到FragmentManager中,此时成员变量mTrendingFragment等指向的是这些活跃的实例。但当Activity被后台回收再重建时,savedInstanceState不为null,你跳过了Fragment的创建逻辑,但系统会自动恢复之前的三个Fragment——这些是新的实例,而你的成员变量依然指向旧的、已经被销毁的Fragment对象。这时候你点击BottomNavigationView执行切换逻辑时,操作的是旧的实例(它们已经不在FragmentManager里了),自然不会有任何界面变化,始终显示的是系统恢复的首页Fragment。
修复方案
解决思路很简单:在Activity重建时,从FragmentManager中重新获取恢复后的Fragment实例,而不是继续使用旧的成员变量。具体代码调整如下:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); FragmentManager fragmentManager = getSupportFragmentManager(); // 优先从FragmentManager中查找已存在的实例(系统恢复的) mUpcomingViewPagerFragment = (UpcomingViewPagerFragment) fragmentManager.findFragmentByTag("1"); mFavoriteFragment = (FavoriteFragment) fragmentManager.findFragmentByTag("2"); mTrendingFragment = (TrendingFragment) fragmentManager.findFragmentByTag("3"); // 只有首次创建时才初始化新的Fragment实例 if (savedInstanceState == null) { mUpcomingViewPagerFragment = new UpcomingViewPagerFragment(); mFavoriteFragment = new FavoriteFragment(); mTrendingFragment = new TrendingFragment(); // 合并FragmentTransaction操作,减少commit次数 FragmentTransaction transaction = fragmentManager.beginTransaction(); transaction.add(R.id.content_main, mTrendingFragment, "3").hide(mTrendingFragment); transaction.add(R.id.content_main, mFavoriteFragment, "2").hide(mFavoriteFragment); transaction.add(R.id.content_main, mUpcomingViewPagerFragment, "1"); transaction.commit(); } // 初始化BottomNavigationView的切换逻辑 BottomNavigationView navView = findViewById(R.id.nav_view); navView.setOnItemSelectedListener(item -> { FragmentTransaction transaction = fragmentManager.beginTransaction(); // 先隐藏所有Fragment transaction.hide(mUpcomingViewPagerFragment); transaction.hide(mFavoriteFragment); transaction.hide(mTrendingFragment); // 根据菜单项显示对应Fragment switch (item.getItemId()) { case R.id.navigation_upcoming: transaction.show(mUpcomingViewPagerFragment); break; case R.id.navigation_favorite: transaction.show(mFavoriteFragment); break; case R.id.navigation_trending: transaction.show(mTrendingFragment); break; } transaction.commit(); return true; }); }
额外注意事项
- 确保你查找Fragment时用的tag和添加时的tag完全一致,否则会找不到系统恢复的实例。
- 尽量合并FragmentTransaction的操作,不要多次调用
commit,这样能提升性能并避免潜在的状态不一致问题。 - 如果你使用的是原生
FragmentManager而非SupportFragmentManager,只需替换对应的类即可,逻辑完全一致。
内容的提问来源于stack exchange,提问作者user9132502
相关产品推荐
相关产品推荐

