Android Jetpack Compose基础之State状态
Stateless和Stateful
什么是Stateless,让我看下面代码
kotlin
@Composable
fun Greeting(name:String){
Text(text = "Hello $name")
}
Greeting方法中未持有或访问了某些状态,它唯一变化的来自参数,所以他就是一个无状态的纯函数;
Stateless它有什么特点呢
1、当无状态函数的参数没有发生改变时,不会参与调用方的重组,将重组范围局限在无状态函数外部;
Stateless它是如何实现避免无效重组的呢
Compose编译器在@Composable注解的函数体内进行了字节码插桩技术,在Text调用之前对参数进行了判断,如果参数没有变化,则跳过对Text的调用,从而避免无效重组。
什么是Stateful,让我看下面代码
kotlin
@Composable
fun GreetingStateful(){
var name by remember{
mutableStateOf("World")
}
Text(text = "Stateful")
Text(text = "Hello $name", modifier = Modifier.clickable {
name ="World ${Random.nextInt(100)}"
})
}
在代码内部我们创建了状态name来记录最新的值,GreetingStateful中依赖对name的读写,因此它时一个Stateful。
Compose中的State
在Compose中使用State描述一个状态,当Composable对state的值进行读取的同时会与state建立订阅关系,当值发生改变时,Composable会自动重组刷新ui
kotlin
@Stable
interface State<out T> {
val value: T//不可修改
}
State子类之MutableState
如果需要对Sate的value进行修改,则需要使用MutableState来表示可修改状态
kotlin
@Stable
interface MutableState<T> : State<T> {
override var value: T //var可修改类型
operator fun component1(): T
operator fun component2(): (T) -> Unit
}
创建方式1:直接赋值
kotlin
val name = mutableStateOf("default")
创建方式2:解构
kotlin
val(name2,setName2) = mutableStateOf("default")
创建方式3:属性代理
kotlin
var name3 by mutableStateOf("default")
状态的恢复与持久化
remember
1、未避免因重组导致状态的丢失,我们常见的是使用remember实现缓存状态
kotlin
var name4 by remember {
mutableStateOf("default")
}
rememberSaveable
2、虽然remember能跨越重组,但是不能跨越Acitivity和进程,这时我们需要使用rememberSaveable
kotlin
var name5 by rememberSaveable {
mutableStateOf("default")
}
rememberSaveable 中的数据会在onSaveInstanceState中以Bundle形式进行保存,在进程或者activity重建时根据key恢复到对应的Composable中,这个key是Compsable在编译期被确定的唯一表述,其源码如下
kotlin
@Composable
fun <T : Any> rememberSaveable(
vararg inputs: Any?,
saver: Saver<T, out Any> = autoSaver(),
key: String? = null,
init: () -> T
): T {
val compositeKey = currentCompositeKeyHash
// key is the one provided by the user or the one generated by the compose runtime
val finalKey = if (!key.isNullOrEmpty()) {
key
} else {
compositeKey.toString(MaxSupportedRadix)
}
@Suppress("UNCHECKED_CAST")
(saver as Saver<T, Any>)
val registry = LocalSaveableStateRegistry.current
val holder = remember {
// value is restored using the registry or created via [init] lambda
val restored = registry?.consumeRestored(finalKey)?.let {
saver.restore(it)
}
val finalValue = restored ?: init()
SaveableHolder(saver, registry, finalKey, finalValue, inputs)
}
val value = holder.getValueIfInputsDidntChange(inputs) ?: init()
SideEffect {
holder.update(saver, registry, finalKey, value, inputs)
}
return value
}
其它方式:
如ViewModel等等方式,不再赘述
------note end------
原理有待探索~~