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

Compose导航:如何根据API响应动态修改启动页面?

基于登录API响应动态设置Jetpack Compose Destinations启动屏幕

核心思路

先在Activity中完成登录状态的API校验,根据响应结果动态指定导航的起始页面,同时处理加载、错误状态避免用户体验问题。


步骤1:管理登录状态与API请求

用ViewModel封装API请求和状态逻辑,确保配置变更时状态不丢失:

class AuthViewModel : ViewModel() {
    private val _authState = MutableStateFlow<AuthState>(AuthState.Loading)
    val authState: StateFlow<AuthState> = _authState

    init {
        checkAuthStatus()
    }

    fun checkAuthStatus() {
        viewModelScope.launch {
            _authState.value = AuthState.Loading
            try {
                // 替换为你的登录状态校验API调用
                val apiResponse = AuthApi.checkUserAuth()
                _authState.value = if (apiResponse.isAuthenticated) {
                    AuthState.Authenticated
                } else {
                    AuthState.Unauthenticated
                }
            } catch (e: Exception) {
                _authState.value = AuthState.Error(e.message ?: "校验失败")
            }
        }
    }
}

sealed class AuthState {
    object Loading : AuthState()
    object Authenticated : AuthState()
    object Unauthenticated : AuthState()
    data class Error(val message: String) : AuthState()
}

步骤2:在Activity中动态渲染导航

根据状态先显示加载/错误界面,API响应返回后再渲染指定起始页的导航宿主:

class MainActivity : ComponentActivity() {
    private val authViewModel: AuthViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            val authState by authViewModel.authState.collectAsStateWithLifecycle()

            when (authState) {
                AuthState.Loading -> {
                    // 显示加载占位
                    Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
                        CircularProgressIndicator()
                    }
                }
                AuthState.Authenticated -> {
                    // 已登录,启动主页
                    DynamicNavHost(startDestination = HomeScreenDestination.route)
                }
                AuthState.Unauthenticated -> {
                    // 未登录,启动登录页
                    DynamicNavHost(startDestination = LoginScreenDestination.route)
                }
                is AuthState.Error -> {
                    // 错误状态,提供重试
                    Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
                        Column(horizontalAlignment = Alignment.CenterHorizontally) {
                            Text((authState as AuthState.Error).message)
                            Button(onClick = { authViewModel.checkAuthStatus() }) {
                                Text("重试")
                            }
                        }
                    }
                }
            }
        }
    }
}

步骤3:改造导航宿主支持动态起始页

修改默认的DestinationsNavHost,允许传入自定义起始页:

@Composable
fun DynamicNavHost(startDestination: String) {
    val navController = rememberNavController()
    DestinationsNavHost(
        navController = navController,
        // 复制根导航图并替换起始页
        navGraph = NavGraphs.root.copy(startDestination = startDestination)
    )
}

可选方案:初始化后跳转(避免修改导航图)

如果不想改动原导航图的start=true配置,可在导航初始化完成后根据状态跳转并清空返回栈:

@Composable
fun DefaultNavHost(authViewModel: AuthViewModel) {
    val navController = rememberNavController()
    val authState by authViewModel.authState.collectAsStateWithLifecycle()

    // 监听状态变化执行跳转
    DisposableEffect(authState) {
        when (authState) {
            AuthState.Authenticated -> {
                navController.navigate(HomeScreenDestination.route) {
                    popUpTo(NavGraphs.root.startRoute) { inclusive = true }
                }
            }
            AuthState.Unauthenticated -> {
                navController.navigate(LoginScreenDestination.route) {
                    popUpTo(NavGraphs.root.startRoute) { inclusive = true }
                }
            }
            else -> {}
        }
        onDispose {}
    }

    DestinationsNavHost(
        navController = navController,
        navGraph = NavGraphs.root
    )
}

关键注意点

  • 优先用「先加载再渲染导航」的方式,避免默认起始页短暂显示后跳转的闪烁问题
  • 跳转时必须清空返回栈(popUpTo + inclusive=true),防止用户按返回键回到默认页面
  • 处理API请求失败的边界情况,提供重试入口提升用户体验

内容的提问来源于stack exchange,提问作者Talha Akbar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 15:51:54