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()
        }
    }
}
相关推荐
JMchen1233 小时前
Android后台服务与网络保活:WorkManager的实战应用
android·java·网络·kotlin·php·android-studio
crmscs3 小时前
剪映永久解锁版/电脑版永久会员VIP/安卓SVIP手机永久版下载
android·智能手机·电脑
localbob3 小时前
杀戮尖塔 v6 MOD整合版(Slay the Spire)安卓+PC端免安装中文版分享 卡牌肉鸽神作!杀戮尖塔中文版,电脑和手机都能玩!杀戮尖塔.exe 杀戮尖塔.apk
android·杀戮尖塔apk·杀戮尖塔exe·游戏分享
机建狂魔3 小时前
手机秒变电影机:Blackmagic Camera + LUT滤镜包的专业级视频解决方案
android·拍照·摄影·lut滤镜·拍摄·摄像·录像
hudawei9963 小时前
flutter和Android动画的对比
android·flutter·动画
lxysbly5 小时前
md模拟器安卓版带金手指2026
android
儿歌八万首6 小时前
硬核春节:用 Compose 打造“赛博鞭炮”
android·kotlin·compose·春节
消失的旧时光-19439 小时前
从 Kotlin 到 Dart:为什么 sealed 是处理「多种返回结果」的最佳方式?
android·开发语言·flutter·架构·kotlin·sealed
Jinkxs9 小时前
Gradle - 与Groovy/Kotlin DSL对比 构建脚本语言选择指南
android·开发语言·kotlin
&有梦想的咸鱼&9 小时前
Kotlin委托机制的底层实现深度解析(74)
android·开发语言·kotlin