Compose Composable和MutableState
- Composable的理解和使用场景
- MutableState的使用和源码浅析
Composable
啥是Composable?
简而言之,带@Composable
注解的函数,就被叫做Composable / Composable
函数
composable注解:
- 用了
comose
控件的函数就需要添加@Composable
注解 - 同样,调用了带
@Composable
注解函数的函数,也需要添加@Composable
注解
使用场景
什么时候需要自定义Composable呢?
在没有compose
之前,如果想要一个灵活的、定制化的view,一般都需要自定义view,而有了compose
,只需要通过自定义Composable
就能实现(传统的xml布局+自定义view)的功能。
Compose的界面刷新三阶段包含:组合(Compose/Composition)、布局、绘制,比传统的过程多了一个组合
组合:执行@Composable代码,创造出实际的界面内容
MutableState
使用MutableState
实现compose
界面的自动刷新,比如3s后自动更新一段Text内容
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 使用by委托需要手动import androidx.compose.runtime.getValue/setValue,目前不支持自动导入
var name by mutableStateOf("composable")
setContent {
Text(name)
}
lifecycleScope.launch {
delay(3000)
name = "composable 3000"
}
}
根据过往的经验,我们可以猜想到这种更新机制肯定是使用了观察者模式的设计思想。稍微浅析一下源码,就可以看出确实是这样:
源码浅析
mutableStateOf
最终返回的是一个MutableState类型,实际是ParcelableSnapshotMutableState,但它主要就是实现了Parcelable的功能
fun <T> mutableStateOf(
value: T,
policy: SnapshotMutationPolicy<T> = structuralEqualityPolicy()
): MutableState<T> = createSnapshotMutableState(value, policy)
internal actual fun <T> createSnapshotMutableState(
value: T,
policy: SnapshotMutationPolicy<T>
): SnapshotMutableState<T> = ParcelableSnapshotMutableState(value, policy)
关键代码是在ParcelableSnapshotMutableState的父类SnapshotMutableStateImpl中,其中最核心是 get()和set()方法
internal open class SnapshotMutableStateImpl<T>(
value: T,
override val policy: SnapshotMutationPolicy<T>
) : StateObject, SnapshotMutableState<T> {
override var value: T
get() = next.readable(this).value
set(value) = next.withCurrent {
if (!policy.equivalent(it.value, value)) {
next.overwritable(this, it) { this.value = value }
}
}
// 链表结构的next指针
private var next: StateStateRecord<T> = StateStateRecord(value)
// 头结点
override val firstStateRecord: StateRecord
get() = next
}
get方法
get方法的关键是遍历链表,根据id获取有效值
get() = next.readable(this).value
fun <T : StateRecord> T.readable(state: StateObject, snapshot: Snapshot): T {
// invoke the observer associated with the current snapshot.
// 通知读观察者
snapshot.readObserver?.invoke(state)
return readable(this, snapshot.id, snapshot.invalid) ?: readError()
}
private fun <T : StateRecord> readable(r: T, id: Int, invalid: SnapshotIdSet): T? {
// The readable record is the valid record with the highest snapshotId
var current: StateRecord? = r
var candidate: StateRecord? = null
while (current != null) {
if (valid(current, id, invalid)) {
candidate = if (candidate == null) current
else if (candidate.snapshotId < current.snapshotId) current else candidate
}
current = current.next
}
if (candidate != null) {
return candidate as T
}
return null
}
set方法
set()
的关键有两步withCurrent()
和overwritable()
。next.withCurrent()
的目的是读取当前的值,用于后面的比较更新。
// next.withCurrent: 读取当前的值
set(value) = next.withCurrent {
if (!policy.equivalent(it.value, value)) {
next.overwritable(this, it) { this.value = value }
}
}
inline fun <T : StateRecord, R> T.withCurrent(block: (r: T) -> R): R =
block(current(this, Snapshot.current))
internal fun <T : StateRecord> current(r: T, snapshot: Snapshot) =
readable(r, snapshot.id, snapshot.invalid) ?: readError()
next.overwritable()
用来更新当前的值并通知观察者
internal inline fun <T : StateRecord, R> T.overwritable(
state: StateObject,
candidate: T,
block: T.() -> R
): R {
var snapshot: Snapshot = snapshotInitializer
return sync {
snapshot = Snapshot.current
// 更新当前的值
this.overwritableRecord(state, snapshot, candidate).block()
}.also {
// 通知更新
notifyWrite(snapshot, state)
}
}
internal fun notifyWrite(snapshot: Snapshot, state: StateObject) {
// 通知写观察者
snapshot.writeObserver?.invoke(state)
}