Skip to content

Commit

Permalink
stable的注解
Browse files Browse the repository at this point in the history
  • Loading branch information
iOrchid committed May 10, 2024
1 parent 6b49c95 commit c560d09
Show file tree
Hide file tree
Showing 2 changed files with 221 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
Expand Down Expand Up @@ -167,12 +170,15 @@ private data class EStr(val str: String)
* ⚠️这里特别说明,非内联,因为常用的Column,Row,Box 容器 是内联的inline composable函数。
* 2、在composable作用域内,只要有状态数据发生变化,就会触发reComposable重组。
* 3、重组会尽量 最小化 触发范围。封装出去的composable函数,即使在一个感受变化的作用域内,如果它不接收变化数据,则 其自身也不会重组。
* 4、初步可以简单理解LaunchEffect、SideEffect、DisposableEffect的感知compose的生命周期的效果
*/
@Composable
private fun UI_ReComposable() {
Title_Text(title = "Recompose重组")
Title_Sub_Text(title = "composable元素生命周期相比Android的activity/fragment简单许多,创建--组合(单/多次)--销毁。而重组的多次绘制也不会影响过多的性能。reCompose会最小化组合元素区域,感知数据变化来触发。")
RC_Simple()
//重组 的作用域
UI_CommonStable()
}

//简单演示 重组 作用域
Expand Down Expand Up @@ -208,6 +214,23 @@ private fun RC_Simple() {
// 而且,⚠️可以注意,log输出不只是Column的进入,而是会有👀开始的那个log,就因为Column是内联,而非独立composable函数
Text(text = "外部的统计数:${counter.intValue}")
}
//composable的控件 三个生命周期:创建--绘制(单/多次)--销毁。不像Activity/Fragment有生命周期回调函数。这里可以用后续会学到的Effect效应函数来监控生命周期
LaunchedEffect(key1 = null) {
//启动效应函数,会在所属composable作用域进行创建的时候,调用且仅调用一次。内部有协程作用域,会伴随所属compose。
println("🚀LaunchEffect创建compose的协程")
}
SideEffect {
//SideEffect 会在compose每次重组都调用
println("♻️每次都会调用。。。")
}
DisposableEffect(key1 = null) {
//销毁compose会调用的效应effect,其内部必须调用onDispose来释放必要的资源
println("🗑️这里如同LaunchEffect一样,初始化调用一次。")
onDispose {
//这里是compose销毁的时候,调用的作用域。
println("💨释放.....资源")
}
}
}


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
package org.zhiwei.compose.screen.state

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.CutCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.Stable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import kotlin.random.Random

/**
* 演示compose中感知数据变化,引起重组;
* 在一些封装的compose独立函数中,接收变化参数与否,会重组与否。
* 添加@stable,@immutable @NonRestartableComposable 等不同的注解,会有不同的作用效果。
* @stable 注解可用于类/接口,函数,会标注稳定的。
* @immutable,标注立即变化的。
*/
@Composable
internal fun UI_CommonStable() {
//三种不同的数据形式
var counter by remember { mutableIntStateOf(0) }
val unstableData by remember { mutableStateOf(UnStableDataClass(0)) }
val unstableData2 by remember { mutableStateOf(UnStableDataClass2(0)) }
val stableData by remember { mutableStateOf(StableDataClas(0)) }

Column {
Button(
onClick = { counter++ },
Modifier
.fillMaxWidth()
.padding(horizontal = 8.dp)
) {
Text(text = "当前数:$counter")
}
Spacer(modifier = Modifier.height(20.dp))
//可观察控制台输出的log看整个重组作用域,也可以看UI运行效果。
OuterComposable {
println("🔥创建OuterComposable ")
MiddleComposable {
// 本区域内有counter变化,所以会引起该区域重组
println("🔥创建MiddleComposable ")
//封装的compose独立函数,即使它们接收的参数没有变化,但是由于所在作用域重组,会引起其自身也重组。
UnstableComposable(data = unstableData)
//这个和上面基本一样,但是data是使用了@stable注解的,所以它不会因为外部区域的重组而重组,除非接收参数真的变化了。
UnstableComposable2(data = unstableData2)
//然而这个compose函数,接收到的参数是val不可变的,且其是非inline的独立compose组件,所以它不会重组。
StableComposable(data = stableData)
Counter(text = "计数 $counter")
}
}
}
}


//含有一个var可变参数的类
data class UnStableDataClass(var value: Int)

//同上,但是添加有@stable注解
@Stable
data class UnStableDataClass2(var value: Int)

//含有val不可变参数的类
data class StableDataClas(val value: Int)

@Composable
private fun UnstableComposable(data: UnStableDataClass) {
SideEffect {
println("🍎 UnstableComposable")
}
Column(
modifier = Modifier
.padding(4.dp)
.shadow(1.dp, shape = CutCornerShape(topEnd = 8.dp))
.background(randomColor())
.fillMaxWidth()
.padding(4.dp)
) {
//而这个data的value是var可变的,外部触发函数作用域的时候,就引起自身也重组。
Text(text = "UnstableComposable() value: ${data.value}")
}
}

//和UnstableComposable基本一致,就是使用的data是不同的类,添加了@stable的注解与否
@Composable
private fun UnstableComposable2(data: UnStableDataClass2) {
SideEffect {
println("🍎 UnstableComposable2")
}
Column(
modifier = Modifier
.padding(4.dp)
.shadow(1.dp, shape = CutCornerShape(topEnd = 8.dp))
.background(randomColor())
.fillMaxWidth()
.padding(4.dp)
) {
//而这个data的value是var可变的,外部触发函数作用域的时候,就引起自身也重组。
Text(text = "UnstableComposable() value: ${data.value}")
}
}


@Composable
private fun StableComposable(data: StableDataClas) {
SideEffect {
println("🍏 StableComposable")
}
Column(
modifier = Modifier
.padding(4.dp)
.shadow(1.dp, shape = CutCornerShape(topEnd = 8.dp))
.background(randomColor())
.fillMaxWidth()
.padding(4.dp)
) {
//因为这个data的value是val的,在函数内就是不会变化的。
Text(text = "StableComposable value(): ${data.value}")
}
}


/**
* 外框
*/
@Composable
private fun OuterComposable(content: @Composable () -> Unit) {
//创建compose的时候会调用
SideEffect {
println("== 外边框的Composable函数 ==")
}

Column(
modifier = Modifier
.padding(4.dp)
.shadow(1.dp, shape = CutCornerShape(topEnd = 8.dp))
.background(randomColor())
.fillMaxWidth()
.padding(4.dp)
) { content() }
}

//中间框
@Composable
private fun MiddleComposable(content: @Composable () -> Unit) {
SideEffect {
println("--- 中间composable ---")
}
Column(
modifier = Modifier
.padding(4.dp)
.shadow(1.dp, shape = CutCornerShape(topEnd = 8.dp))
.background(randomColor())
.fillMaxWidth()
.padding(4.dp)
) { content() }
}

//计数显示
@Composable
private fun Counter(text: String) {
SideEffect {
println("--->>> 🧮🔢$text🧄⬆️ <<<---")
}
Column(
modifier = Modifier
.padding(4.dp)
.shadow(1.dp, shape = CutCornerShape(topEnd = 8.dp))
.background(randomColor())
.fillMaxWidth()
.padding(4.dp)
) {
Text(text = "计数框: $text")
}
}

private fun randomColor(): Color {
return Color(
Random.nextInt(255),
Random.nextInt(255),
Random.nextInt(255),
Random.nextInt(255),
)
}

0 comments on commit c560d09

Please sign in to comment.