compose 中的附带效应笔记一

通常情况下状态发生改变时想要更新UI,我们会使用 var value by remeber { mutableStateOf() }来创建一个可观察的状态数据。当state的数据发生改变以后,使用了state数据组件会发生重组,从而实现刷新。 但有些情况下,我们想要实现在可组合函数中执行一次网络请求,根据请求结果改变界面状态,或者执行挂起函数再改变界面状态。此时需要用到附带效应。

1.LaunchedEffect

launchedEffect主要作用是让你在Composable作用域里实现协程工作,来完成异步、耗时操作、网络请求等

kotlin 复制代码
@Composable
fun LunchedEffectTest(){
    var value by remeber{ mutableStateOf() }
    LaunchedEffect(key){ //key如果没有发生变化,则重组中不会启动新的协程
        while(true){
            delay(100)
            value++
        }
    }
    
    Text(text='${value}')
}

2.rememberCoroutineScope

LanchedEffect只能在composable作用域内调用,无法在按键点击回调等地方调用。rememberCoroutineScope可以在这些地方调用。

kotlin 复制代码
@Composable
fun rememberCoroutineScopeTest(){
    val scope = rememberCoroutineScope()
    Button(
        onclick={
            scope.launch{
                //模拟网络请求
            }
        }{
        Text("请求数据")
        }
    )
   
}

3.rememberUpdateState 只是辅助LaunchedEffect向外部(其他composeable方法)更新状态功能,用于在不同compose方法下LaunchedEffect的数据更新时提供更新数据。

kotlin 复制代码
@Composable
fun RemeberUpdateStateTest(){
    var name by remember { mutableStateOf("") }
    RemeberUpdateStateUI(name = name,onValueChanged = {
        name = it
    })
}

@Composable
fun RemeberUpdateStateUI(name:String,onValueChanged:(String) -> Unit){
    val nameUpdateState = remmberUpdateState(name)

    LaunchedEffect(key){  //key保持一致可以为true
        delay(1000)
        //Log.d("RemeberUpdateStateUI","$name") //正常情况下如果这里输入框输入完以后,这里最后结果并不是预期的,比如输入框111222,但是这里可能1000毫秒以后,name还是111,所以要用remeberUpdateState包装一下。
        //nameUpdateState 包装后的结果,这里获取的nameUpdateState对象中的值就是111222
    }
    
    OutLinedTextField(
        value = name,
        onValueChange = onValueChanged
    )
    
}

工作原理分析: rememberUpdatedState 的内部逻辑可以简化为以下核心思想:

  1. 创建一个持久的 MutableState 容器 :这个容器通过 remember 在重组中保持不变。
  2. 在每次重组时更新该容器的值 :无论 key 是否变化,只要可组合函数被调用,它就会将 newValue 更新到内部的 MutableState 中。
  3. 返回该容器的引用:效应内部通过这个稳定的引用,读取到的永远是最新存入的值。

其内部实现类似于以下的简化逻辑(概念模型):

kotlin 复制代码
@Composable
fun <T> rememberUpdatedState(newValue: T): State<T> = remember {
    mutableStateOf(newValue)
}.apply { value = newValue }
// 注意:每次重组都会执行 `.apply { value = newValue }` 来更新值

4.SideEffect

SideEffect相当于DisposableEffect的简化,当不需要onDispose,不需要参数控制。compose操作非原子操作,重组中可能发生意外。

kotlin 复制代码
  @Composable
  fun sideEffectTest(user:User){
      val count = remember { mutableStateOf(0) }
      SideEffect{
          count = user.number
      }
      Text(text = count.value.toString,modifier = Modifier.clickable={
         count.value ++
      })
      
  }

5.DispoableEffect

DispoableEffect必须添加一个onDispose 方法,此方法一般用于处理资源清理和释放。另外DisposableEffect也带参数意义和LaunchedEffect的参数一样。

kotlin 复制代码
@Composable
fun DisposableEffectTest(dispatcher:OnBackPressDispather){
    val backCallback = remember { 
        object:OnBackPressCallback(true){
            override fun handleOnBackPressed(){
                //TODO
            }
        }
    }
    
    DisposableEffect(dispatcher){
        dispatcher.addCallback(backCallback)
        onDispose{
            backCallback.remove()
        }
    }
}
相关推荐
胖大师6 小时前
Android Audio-FW
android
kayyoo8 小时前
CoordinatorLayout解析(二): 结合CollapsingToolbarLayout实现Toolbar折叠效果
android
数据知道9 小时前
移动端渗透测试流程:Android APK 逆向与动态调试
android·web安全·网络安全
我命由我1234511 小时前
人脸识别 - 勒克斯(光线照射到物体表面上的明亮程度)
android·java·学习·java-ee·人脸识别·学习方法·android runtime
聚美智数11 小时前
护照OCR识别-护照图像识别-护照OCR文字识别-护照识别OCR-护照信息识别-护照OCR
android·ocr
码农coding13 小时前
android12 点击桌面应用图标启动Activity流程
android
johnsong13 小时前
深度拆解:150M循环模型如何用循环推理击败大Transformer
android·深度学习·transformer
CedarQR14 小时前
云卓 G20 遥控器 Android 开发实录:从 USB 设备到读取摇杆/按键通道值
android·linux·无人机
pengyu15 小时前
【Kotlin 协程修仙录 · 炼虚境 · 初阶】 | 虚空造物:Channel 基础与协程间通信的管道艺术
android·前端·kotlin
小强闯江湖15 小时前
ViewCompose:让原生 Android View 进入声明式时代
android·开源·kotlin