Compose通过一系列Effects
方法实现生命周期函数,类似React的Hooks Api
Compose Lifecycle
同样是声明式UI框架,所以Compose的生命周期函数可以与React进行类比
Compose生命周期 | 说明 | 对应的React |
---|---|---|
onActive | compose函数第一次被渲染到画面 | componentWillMount componentDidMount |
onDispose | compose函数从画面上移除 | componentWillUnmount |
onCommit | compose函数每次执行,画面重新渲染 | componentDidUpdate |
onPreCommit | compose函数每次执行之前 | componentWillUpdate |
可观察参数
onCommit
和onPreCommit
的使用类似React的useEffect
,支持可观察参数
@Composable fun <V1> onCommit(
v1: V1,
callback: CommitScope.() -> Unit
): Unit
@Composable fun <V1> onPreCommit(
v1: V1,
callback: CommitScope.() -> Unit
): Unit
仅当v1发生变化时onCommit
或者onPreCommit
才会执行
onDispose
onDispose
可以在onCommit
或者onPreCommit
中使用,当前Effect结束时会进行回调进行一些配对的后处理,例如一些注册和反注册
onPreCommit(true) {
//... do sth regist
onDispose {
//... do sth ungister
}
}
这与useEffect
返回一个function进行后处理的机制也很类似。下一次Effect被调用时调用前一次的onDispose
,所以每个Effect的生命周期持续到下次调用为止。
与React的不同
Compose的生命周期函数从API设计到语义与React的useEffect等Hooks非常相似,但是有一点非常的不同
Don’t call Hooks inside loops, conditions, or nested functions. Instead, always use Hooks at the top level of your React function. By following this rule, you ensure that Hooks are called in the same order each time a component renders.
– Rules of Hooks
Hooks的本质是使用Effect将缓存Callback(onCommit等cb并非每次执行),缓存的管理需要使用自增key,为了避免key的乱序,Hooks不允许出现在if等控制语句中,只能出现在top-level。
Compose通过Compiler Plugin在编译期为if等控制语句加入唯一Key,所以不会出现React的乱序的问题,因此Compose允许在Effect只出现在if中,如下:
@Composable
fun LifecycleDemo() {
val count = state { 0 }
Column {
Button(onClick = {
count.value++
}) {
Text("Click me")
}
if (count.value < 3) {
onActive { Log.d("Compose", "onactive with value: " + count.value) }
onDispose { Log.d("Compose", "onDispose because value=" + count.value) }
Text("You have clicked the button: " + count.value.toString())
}
}
}
onActive
会在第一次进入if时调用,当count达到3时,if不会进入,onDispose
会在此时执行