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

Jetpack Compose:切换底部导航时先显示加载器再渲染页面

实现即时跳转+加载状态的底部导航页面切换

要实现点击底部导航后立即跳转显示加载器,待API返回数据再渲染页面,核心是将页面的数据加载逻辑从组件初始化同步执行改为异步触发,并在页面内部维护加载状态,具体实现方案如下:

1. 重构页面组件,添加状态管理

每个页面组件需内部维护加载状态,进入页面后立即触发异步API请求,根据请求状态切换UI:

@Composable
fun RenderTransactionsScreen(context: Context) {
    // 维护加载状态,初始为true
    val isLoading = remember { mutableStateOf(true) }
    // 存储页面数据,根据实际业务调整类型
    val transactionsData = remember { mutableStateOf<List<Transaction>>(emptyList()) }
    val errorMessage = remember { mutableStateOf<String?>(null) }

    // 页面首次进入时触发API请求
    LaunchedEffect(Unit) {
        try {
            // 替换为你的实际后端API请求逻辑
            val data = fetchTransactionsFromApi(context)
            transactionsData.value = data
        } catch (e: Exception) {
            errorMessage.value = e.localizedMessage
        } finally {
            // 请求完成(成功/失败)都结束加载状态
            isLoading.value = false
        }
    }

    // 根据状态渲染对应UI
    when {
        isLoading.value -> {
            // 加载中:居中显示圆形加载器
            Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
                CircularProgressIndicator(color = MaterialTheme.colorScheme.primary)
            }
        }
        errorMessage.value != null -> {
            // 加载失败:显示错误提示(可选)
            Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
                Text(text = errorMessage.value ?: "加载失败", color = MaterialTheme.colorScheme.error)
            }
        }
        else -> {
            // 加载完成:渲染完整页面内容
            TransactionsContent(data = transactionsData.value)
        }
    }
}

// 实际API请求需改为挂起函数,避免阻塞UI线程
suspend fun fetchTransactionsFromApi(context: Context): List<Transaction> {
    // 模拟网络延迟,实际场景替换为Retrofit/OkHttp请求
    delay(1500)
    return listOf(
        Transaction("午餐消费", "2024-05-20", 45.0),
        Transaction("交通补贴", "2024-05-19", 100.0)
    )
}

// 页面核心内容组件(提取原RenderTransactionsScreen的渲染逻辑)
@Composable
fun TransactionsContent(data: List<Transaction>) {
    LazyColumn(modifier = Modifier.fillMaxSize()) {
        items(data) { transaction ->
            ListItem(
                headlineContent = { Text(transaction.title) },
                supportingContent = { Text(transaction.date) },
                trailingContent = { Text("¥${transaction.amount}") }
            )
        }
    }
}

// 模拟数据类,根据实际业务替换
data class Transaction(val title: String, val date: String, val amount: Double)

2. 对其他页面执行同样改造

按照上述模式,修改RenderSummaryScreen和RenderProfileScreen,确保每个页面都能在进入时立即显示加载器,异步加载数据。

3. 保持原有导航逻辑不变

原有的NavigationController和Navigation组件无需修改,因为NavHost在调用navController.navigate时会立即切换到目标页面组件,我们已经将页面的同步加载逻辑改为异步,因此页面会先显示加载器,不会阻塞跳转流程。

关键细节说明

  • LaunchedEffect(Unit):确保页面首次组合时仅触发一次API请求,避免重复请求。
  • 状态驱动UI:用mutableStateOf维护加载状态、数据和错误信息,Compose会自动根据状态变化重组UI。
  • 异步请求:API请求必须使用挂起函数(suspend修饰),保证不会阻塞UI线程,确保跳转的即时性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 21:55:14