如何在Navigation架构组件中实现条件导航?含单Activity场景诉求
针对你的单Activity场景(LoginFragment仅需进入一次,默认startDestination设为HomeFragment,但要在加载前检查登录状态),这里分享几个实用且贴合需求的方案:
方案1:动态设置导航图的起始目的地(推荐)
这个方案能避免先加载Home再跳转的闪烁问题,启动时就直接定位到正确页面,体验更流畅:
在MainActivity的onCreate方法中,初始化NavController后,根据login_flag动态修改导航图的startDestination:
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val navController = findNavController(R.id.nav_host_fragment_container) val sharedPrefs = getSharedPreferences("app_prefs", MODE_PRIVATE) val isLoggedIn = sharedPrefs.getBoolean("login_flag", false) // 加载导航图并动态配置起始页 val navInflater = navController.navInflater val navGraph = navInflater.inflate(R.navigation.nav_graph) navGraph.startDestination = if (isLoggedIn) R.id.homeFragment else R.id.loginFragment navController.graph = navGraph } }
登录成功后的收尾处理:在LoginFragment完成登录逻辑后,跳转到HomeFragment并清空返回栈(避免用户按返回键回到Login):
// LoginFragment中登录成功的回调方法 private fun onLoginSuccess() { // 更新登录状态标记 getSharedPreferences("app_prefs", MODE_PRIVATE) .edit() .putBoolean("login_flag", true) .apply() // 导航到Home并移除LoginFragment出栈 findNavController().navigate( R.id.action_login_to_home, null, NavOptions.Builder() .setPopUpTo(R.id.loginFragment, inclusive = true) .build() ) }
方案2:用目的地变化监听器全局拦截导航
如果需要在任何场景下(比如用户从其他页面跳转回Home时)都校验登录状态,可以给NavController添加OnDestinationChangedListener,拦截到Home的导航请求:
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val navController = findNavController(R.id.nav_host_fragment_container) val sharedPrefs = getSharedPreferences("app_prefs", MODE_PRIVATE) navController.addOnDestinationChangedListener { _, destination, _ -> val isLoggedIn = sharedPrefs.getBoolean("login_flag", false) // 若要跳转Home但未登录,拦截并跳转到Login if (destination.id == R.id.homeFragment && !isLoggedIn) { navController.navigate( R.id.loginFragment, null, NavOptions.Builder() .setPopUpTo(R.id.homeFragment, inclusive = true) // 移除Home避免返回 .build() ) } } } }
这个方案适合需要全局管控Home页面访问权限的场景,比如用户登录状态过期后,从其他页面返回Home时会自动触发登录跳转。
方案3:启动时直接判断导航(基础版)
这是最直观的方式,在Activity初始化完成后直接检查登录状态,未登录则导航到Login:
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val navController = findNavController(R.id.nav_host_fragment_container) val sharedPrefs = getSharedPreferences("app_prefs", MODE_PRIVATE) val isLoggedIn = sharedPrefs.getBoolean("login_flag", false) // 未登录且当前页面不是Login时,执行导航 if (!isLoggedIn && navController.currentDestination?.id != R.id.loginFragment) { navController.navigate(R.id.loginFragment) } } }
注意:这个方案可能会出现HomeFragment短暂加载后再跳转Login的闪烁问题,所以优先推荐方案1。
内容的提问来源于stack exchange,提问作者Shashi Kiran
相关产品推荐
相关产品推荐

