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

如何在Navigation架构组件中实现条件导航?含单Activity场景诉求

新版Navigation组件实现条件导航的几种方案

针对你的单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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:51:57