Android Navigation Component未登录跳转欢迎Activity及报错解决方案咨询
报错原因
你报错的核心原因是 onCreateView 阶段刚inflate出来的View还没有附加到NavHostFragment上,无法通过View查找到NavController,所以抛出IllegalStateException。
最优实现方案:提前到MainActivity做登录校验
这种方式可以避免不必要的HomeFragment加载,性能最优,逻辑也更清晰。修改MainActivity的onCreate代码:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 先做登录校验,再初始化视图 SharedPreferences getSharedData = getSharedPreferences("MyApp", Context.MODE_PRIVATE); Boolean loggedIn = getSharedData.getBoolean("isUserLoggedIn", false); if (!loggedIn) { startActivity(new Intent(this, WelcomeActivity.class)); finish(); // 直接返回,不执行后续的视图初始化逻辑 return; } setContentView(R.layout.activity_main); // 后面原有逻辑保持不变 Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); FragmentManager supportFragmentManager = getSupportFragmentManager(); NavHostFragment navHostFragment = (NavHostFragment) supportFragmentManager.findFragmentById(R.id.nav_host_fragment); NavController navController = navHostFragment.getNavController(); AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(R.id.homeFragment, R.id.secondFragment, R.id.thirdFragment, R.id.fourthFragment).build(); NavigationUI.setupWithNavController(toolbar, navController, appBarConfiguration); BottomNavigationView bottomNav = findViewById(R.id.bottom_nav); NavigationUI.setupWithNavController(bottomNav, navController); }
WelcomeActivity登录成功后直接finish自己,就会回到已经完成初始化的MainActivity展示HomeFragment。如果担心用户按返回键回到未初始化的MainActivity,可以给WelcomeActivity设置android:launchMode="singleTask",或者在登录成功后主动启动MainActivity再finish WelcomeActivity。
方案二:保留Fragment内校验的修复方式
如果你一定要在HomeFragment内做校验,把跳转逻辑移到onViewCreated生命周期,并且使用Fragment专属的NavController获取方式即可:
@Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); SharedPreferences getSharedData = requireActivity().getSharedPreferences("MyApp", Context.MODE_PRIVATE); Boolean loggedIn = getSharedData.getBoolean("isUserLoggedIn", false); if (!loggedIn) { // 直接通过Fragment获取NavController,不需要拿View查找 NavHostFragment.findNavController(this).navigate(R.id.welcomeActivity); return; } // 后续加载首页数据逻辑 }
可选优化:单Activity架构适配
如果你不想用独立的WelcomeActivity,可以把欢迎/登录页做成Fragment,动态设置导航图的起始目的地,完全契合单Activity架构:
- 把导航图里的
welcomeActivity节点换成welcomeFragment节点 - 修改MainActivity中NavController初始化部分的代码:
NavController navController = navHostFragment.getNavController(); // 动态设置起始目的地 SharedPreferences getSharedData = getSharedPreferences("MyApp", Context.MODE_PRIVATE); Boolean loggedIn = getSharedData.getBoolean("isUserLoggedIn", false); NavGraph navGraph = navController.getNavInflater().inflate(R.navigation.nav_graph); if (loggedIn) { navGraph.setStartDestination(R.id.homeFragment); } else { navGraph.setStartDestination(R.id.welcomeFragment); } navController.setGraph(navGraph); // 新增目的地切换监听,控制Toolbar和BottomNavigation的显隐 navController.addOnDestinationChangedListener((controller, destination, arguments) -> { if (destination.getId() == R.id.welcomeFragment) { toolbar.setVisibility(View.GONE); bottomNav.setVisibility(View.GONE); } else { toolbar.setVisibility(View.VISIBLE); bottomNav.setVisibility(View.VISIBLE); } });
欢迎Fragment登录成功后调用navController.navigate(R.id.homeFragment),同时pop掉欢迎页的回退栈即可,整个流程都在MainActivity内完成,不需要切换Activity。
内容的提问来源于stack exchange,提问作者cesarcarlos
相关产品推荐
相关产品推荐

