Jetpack Compose页面进入时如何从网络或数据库加载数据
解决方案
你要实现的两个功能都可以通过Compose官方提供的LaunchedEffect完成,这是官方推荐的标准方案,实现逻辑非常简单,不存在额外复杂度。
第一步:修正状态声明
你原来的json是普通Kotlin变量,值修改后不会触发Compose重组,界面不会同步更新,首先需要修改为可观察状态:
// 先导入依赖 import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.runtime.LaunchedEffect import kotlinx.coroutines.delay import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext
@Composable fun DemoScreen(navController: NavController) { // 改为可观察状态,修改后自动触发界面更新 var json by remember { mutableStateOf("Placeholder content, to be updated on screen load and refreshed every x seconds...") } // 可选:加载状态,用来控制进度提示显示 var isLoading by remember { mutableStateOf(false) }
第二步:实现进入页面自动加载+定时刷新
直接在函数内添加LaunchedEffect代码块即可,它会和当前Composable的生命周期绑定,页面退出时内部协程自动取消,不会产生内存泄漏:
// key设为Unit表示仅在当前页面首次进入时执行一次,页面重建、普通重组都不会重复触发 LaunchedEffect(Unit) { // 首次进入先执行一次加载 isLoading = true json = loadData() isLoading = false // 定时循环刷新,示例为30秒刷新一次,可自行调整间隔时间 while(true) { delay(30 * 1000) // 时间单位为毫秒 isLoading = true json = loadData() isLoading = false } } // 封装你的数据请求逻辑 suspend fun loadData(): String { return withContext(Dispatchers.IO) { try { // 这里替换为你的真实API请求/数据库查询逻辑 "请求到的新数据 ${System.currentTimeMillis()}" } catch (e: Exception) { "请求失败:${e.message}" } } }
第三步:可选添加加载进度提示
可以在你原有的Box布局中增加居中的加载进度条,加载状态时显示:
Box(modifier = Modifier .fillMaxWidth() .fillMaxHeight() ){ // 原有Column主内容区域代码保持不变 Column( horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, modifier = Modifier .fillMaxWidth() .padding(horizontal = 0.dp) ) { // 原有TextField、Button代码不用修改 TextField( value = json, onValueChange = { json = it }, singleLine = false, modifier = Modifier .fillMaxWidth() .padding(5.dp) .height(500.dp), maxLines = 10, ) val coroutineScope = rememberCoroutineScope() Button( onClick = { coroutineScope.launch { withContext(Dispatchers.IO) { try { //按钮点击逻辑 } catch (e: Exception) { Log.d("button", e.message.toString()) } finally { Log.d("button", "in finally") } } } }, modifier = Modifier .fillMaxWidth() .padding(5.dp) .height(100.dp) ) { Text(text = "Demo Button") } } // 新增:加载时显示进度条 if (isLoading) { CircularProgressIndicator(modifier = Modifier.align(Alignment.Center)) } } }
说明
如果后续需要根据页面入参变化重新加载数据,只需要把LaunchedEffect的key从Unit改为对应的参数即可,参数变化时会自动取消旧的协程,执行新的加载逻辑。
内容的提问来源于stack exchange,提问作者Pawan Pillai
相关产品推荐
相关产品推荐

