网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
modifier = Modifier.fillMaxSize()wrapContentSize(Alignment.Center)
) {
Text(text = txt)
Button(onClick = {
//在onClick中启动了协程
coroutineScope.launch {
delay(3000)
txt = "修改文案"
}
}) {
Text(text = "rememberCoroutineScope")
}
}
}
点击Button后,启动协程,在协程中延迟3s重组并刷新Text文案。
#### DisposableEffect
@Composable
@NonRestartableComposable
fun DisposableEffect(
key1: Any?,
effect: DisposableEffectScope.() -> DisposableEffectResult
) {
remember(key1) { DisposableEffectImpl(effect) }
}
对于需要在键发生变化或可组合项退出组合后进行清理的副作用,可以使用 DisposableEffect。如果 DisposableEffect 中的key发生变化,那么就会执行onDispose()资源释放等操作,并重新执行DisposableEffect。
**DisposableEffect中强制以onDispose进行收尾,不加就会编译报错**。因此DisposableEffect适合有资源需要收尾的场景下。
使用示例:
@Composable
fun HomeScreen(
lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current,
onStart: () -> Unit, // Send the ‘started’ analytics event
onStop: () -> Unit // Send the ‘stopped’ analytics event
) {
// Safely update the current lambdas when a new one is provided
val currentOnStart by rememberUpdatedState(onStart)
val currentOnStop by rememberUpdatedState(onStop)
// If `lifecycleOwner` changes, dispose and reset the effect
DisposableEffect(lifecycleOwner) {
// Create an observer that triggers our remembered callbacks
// for sending analytics events
val observer = LifecycleEventObserver { _, event ->
if (event == Lifecycle.Event.ON_START) {
currentOnStart()
} else if (event == Lifecycle.Event.ON_STOP) {
currentOnStop()
}
}
// Add the observer to the lifecycle
lifecycleOwner.lifecycle.addObserver(observer)
// When the effect leaves the Composition, remove the observer
onDispose {
lifecycleOwner.lifecycle.removeObserver(observer)
}
}
/* Home screen content */
}
LaunchedEffect 内部开启了协程,并在退出组合时取消协程,DisposableEffect + rememberCoroutineScope 的方式可以模拟 LaunchedEffect,如下:
//LaunchedEffect
LaunchedEffect(key1 = Unit) {
}
//DisposableEffect + rememberCoroutineScope
val scope = rememberCoroutineScope()
DisposableEffect(key1 = Unit) {
val job = scope.launch { }
onDispose {
job.cancel()
}
}
#### rememberUpdatedState
LaunchedEffect(key) 会在key发生变化时会重启协程,如果不希望key变化时协程中断而是继续执行,可以通过 rememberUpdatedState 获取最新状态即可。
@Composable
fun rememberUpdatedState(newValue: T): State = remember {
mutableStateOf(newValue)
}.apply { value = newValue }
//MutableState
@Stable
interface MutableState : State {
override var value: T //rememberUpdatedState每次重组时都会对该值进行更新
operator fun component1(): T
operator fun component2(): (T) -> Unit
}
rememberUpdatedState 源码很简单,内部通过 remember + mutableStateOf 的方式,保证每次重组时都会将newValue 值进行更新到MutableState.value中,最终副作用里访问的也是最新的newValue了,从而实现副作用在不中断的前提下访问到最新传入的值。使用示例如下:
@Composable
fun LandingScreen(onTimeout: () -> Unit) {
// LandingScreen重组时会引用到最新的onTimeout函数
val currentOnTimeout by rememberUpdatedState(onTimeout)
// 如果发生重组,delay函数不会再次执行了;而currentOnTimeout却是最新的onTimeout函数。
LaunchedEffect(true) {
delay(SplashWaitTimeMillis)
currentOnTimeout()
}
/* Landing screen content */
}
#### SideEffect
SideEffect 在每次成功重组时都会执行,这么看好像SideEffect 并不能处理什么副作用呀。其实还是有点区别的,SideEffect只会在重组成功之后才会执行,如果重组失败,那么SideEffect中的lambda将不再执行,以免在当前组合操作失败时使对象处于不一致状态。
使用示例:
@Composable
fun SideEffectStudy() {
Log.e(“Tag”, “SideEffect launch”)
throw IllegalArgumentException(“exception throw”)
}
上述可组合项执行时会抛出异常,在抛异常之前会先输出Log。如果我们想重组成功之后再输出Log该怎么办呢?这时候就可以使用SideEffect了:
@Composable
fun SideEffectStudy() {
SideEffect {
Log.e(“Tag”, “SideEffect launch”)
}
throw IllegalArgumentException(“exception throw”)
}
可以看到将Log日志放到了SideEffect内部,这样就可以保证只有成功重组后才会执行SideEffec t内部的lambda。
#### 总结
* `LaunchedEffect` 内部会启动协程,所以适合当副作用中有耗时任务时的场景下;
* `rememberCoroutineScope`当需要在可组合项外启动协程时(如onClick中),可以使用rememberCoroutineScope
* `DisposableEffect` 适合有资源需要收尾的场景下,内部一定要重写onDispose(),用于释放资源、解注册等操作;
* `rememberUpdatedState` 对于包含长期操作的副作用很有效,尤其适合用在重启这些操作时代价高昂的场景中;
* `SideEffect` 每次重组时都会执行内部的lambda,不过SideEffect 能确保可组合项成功重组之后才会执行内部的 Lambda。
这篇文章主要讲了Compose是什么以及我们要开始学习它的必要性。最后为了帮助大家更好的熟知 Jetpack Compose 这一套体系的知识点,**这里记录比较全比较细致的[《Jetpack 入门到精通》(内含Compose)]( ) 学习笔记!!! 对Jetpose Compose这块感兴趣的小伙伴可以参考学习下……**
### Jetpack 全家桶(Compose)
**Jetpack 部分**
1. Jetpack之Lifecycle
![img](https://img-blog.csdnimg.cn/img_convert/f06f94bab9e107f34e9f5b532d48adcf.png)
![img](https://img-blog.csdnimg.cn/img_convert/c6f1799f7aed9d5a9c69955e09d50d20.png)
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化的资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618636735)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化的资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618636735)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**