抽离BottomNavigation到自定义类后FragmentManager未绑定宿主报错如何解决?
报错原因
- 核心错误:你在自定义
BottomNavigation类中主动new FragmentActivity()创建了全新的Activity实例,这个实例没有经过系统的Activity生命周期初始化,未绑定到系统宿主,所以它持有的FragmentManager处于未挂载状态,调用时直接触发异常。你在MainActivity中传入的this本身就是可用的Activity实例,完全不需要额外新建。 - 次要问题:你自定义的
BottomNavigation本身就继承自BottomNavigationView,初始化逻辑中仍调用findViewById(R.id.bottom_navigation)查找控件,如果你没有将new出来的BottomNavigation实例主动添加到MainActivity的布局中,这行代码会触发空指针异常。
修复方案
按以下步骤修改即可解决问题:
- 移除自定义类中主动创建FragmentActivity的逻辑,直接复用构造传入的MainActivity实例,同时把
FragmentManager的获取逻辑放到构造方法中执行。 - 直接使用当前实例作为导航控件,不需要额外
findViewById查找。
修改后的BottomNavigation类代码:
public class BottomNavigation extends BottomNavigationView { final Fragment homeFragment = new HomeFragment(); final Fragment searchFragment = new SearchFragment(); final Fragment videosFragment = new VideosFragment(); final Fragment favouriteFragment = new FavouriteFragment(); final Fragment premiumFragment = new PremiumFragment(); FragmentManager fragmentManager; Fragment mainFragment = homeFragment; public BottomNavigation(@NonNull Context context) { super(context); // 传入的context就是MainActivity,直接强转获取可用的FragmentManager if (context instanceof FragmentActivity) { fragmentManager = ((FragmentActivity) context).getSupportFragmentManager(); } } @SuppressLint("NonConstantResourceId") public void initializeBottomNavigation() { if (fragmentManager == null) return; // 批量添加所有Fragment FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); fragmentTransaction.add(R.id.fragment_layout, premiumFragment, "5").hide(premiumFragment); fragmentTransaction.add(R.id.fragment_layout, favouriteFragment, "4").hide(favouriteFragment); fragmentTransaction.add(R.id.fragment_layout, videosFragment, "3").hide(videosFragment); fragmentTransaction.add(R.id.fragment_layout, searchFragment, "2").hide(searchFragment); fragmentTransaction.add(R.id.fragment_layout, homeFragment, "1"); // 用commitNow避免异步提交的时序问题,原有逻辑也可保留commit fragmentTransaction.commitNow(); // 直接用当前实例设置监听,不需要findViewById setOnItemSelectedListener(item -> { FragmentTransaction localFragmentTransaction = fragmentManager.beginTransaction(); switch (item.getItemId()) { case R.id.home_item: localFragmentTransaction.hide(mainFragment).show(homeFragment).commit(); mainFragment = homeFragment; return true; case R.id.search_item: localFragmentTransaction.hide(mainFragment).show(searchFragment).commit(); mainFragment = searchFragment; return true; case R.id.videos_item: localFragmentTransaction.hide(mainFragment).show(videosFragment).commit(); mainFragment = videosFragment; return true; case R.id.saved_item: localFragmentTransaction.hide(mainFragment).show(favouriteFragment).commit(); mainFragment = favouriteFragment; return true; case R.id.premium_item: localFragmentTransaction.hide(mainFragment).show(premiumFragment).commit(); mainFragment = premiumFragment; return true; } return false; }); } }
如果你的MainActivity布局XML中已经定义了自定义BottomNavigation(需要替换为你实际的包名),id为R.id.bottom_navigation,可以直接修改MainActivity的初始化代码:
private void initializeBottomNavigation() { // 直接从布局中获取实例,不需要新建 BottomNavigation bottomNavigation = findViewById(R.id.bottom_navigation); bottomNavigation.initializeBottomNavigation(); }
如果你是动态添加控件,只需要把new出来的BottomNavigation实例主动添加到布局容器中即可。
内容的提问来源于stack exchange,提问作者Moataz
相关产品推荐
相关产品推荐

