Compose Composable和MutableState

  1. Composable的理解和使用场景
  2. 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)
}

results matching ""

    No results matching ""