flow的核心api:
1.声明一个stateFlow
2.更改stateFlow的值,setValue
3.调用collect函数,接收value的值
1.构建一个stateFlow对象
public fun <T> MutableStateFlow(value: T): MutableStateFlow<T> = StateFlowImpl(value ?: NULL)
这是一个函数,返回一个 StateFlowImpl (这个是对象),一定会有默认值 Null
2.setValue解析
private class StateFlowImpl<T>(
initialState: Any // T | NULL
) : AbstractSharedFlow<StateFlowSlot>(), MutableStateFlow<T>, CancellableFlow<T>, FusibleFlow<T> {
private val _state = atomic(initialState) // T | NULL
private var sequence = 0 // serializes updates, value update is in process when sequence is odd
@Suppress("UNCHECKED_CAST")
public override var value: T
get() = NULL.unbox(_state.value)
set(value) { updateState(null, value ?: NULL) }
可以看到初始值,被atomic()函数包裹,这个是 “atomicfu”库的一个函数,需要单独添加依赖。
-
updateState()
private fun updateState(expectedState: Any?, newState: Any): Boolean { var curSequence = 0 var curSlots: Array<StateFlowSlot?>? = this.slots // benign race, we will not use it synchronized(this) { val oldState = _state.value if (expectedState != null && oldState != expectedState) return false // CAS support if (oldState == newState) return true // Don't do anything if value is not changing, but CAS -> true _state.value = newState curSequence = sequence if (curSequence and 1 == 0) { // even sequence means quiescent state flow (no ongoing update) curSequence++ // make it odd sequence = curSequence } else { // update is already in process, notify it, and return sequence = curSequence + 2 // change sequence to notify, keep it odd return true // updated } curSlots = slots // read current reference to collectors under lock } /* Fire value updates outside of the lock to avoid deadlocks with unconfined coroutines. Loop until we're done firing all the changes. This is a sort of simple flat combining that ensures sequential firing of concurrent updates and avoids the storm of collector resumes when updates happen concurrently from many threads. */ while (true) { // Benign race on element read from array curSlots?.forEach { it?.makePending() } // check if the value was updated again while we were updating the old one synchronized(this) { if (sequence == curSequence) { // nothing changed, we are done sequence = curSequence + 1 // make sequence even again return true // done, updated } // reread everything for the next loop under the lock curSequence = sequence curSlots = slots } } }
flow对象中,将我们的值变成了一个成员变量,从这个意义上来讲,flow本身就是对变量的封装,就像User对name的封装一样。 更新完成数据之后,下面一个while(true)循环,将更新之后的对象 fire 出去,其他都是一些状态变量的判断。 (晦涩难懂,刚去看了一下suspendCoroutineUninterceptedOrReturn的概念)
4.makePending最终走到了 Continuation.resumeWith()方法。
public interface Continuation<in T> {
/**
* The context of the coroutine that corresponds to this continuation.
*/
public val context: CoroutineContext
/**
* Resumes the execution of the corresponding coroutine passing a successful or failed [result] as the
* return value of the last suspension point.
*/
public fun resumeWith(result: Result<T>)
}
这个方法本质上是让协程 结束挂起状态。
-
上面理解有点不通,先看collect{}方法。
override suspend fun collect(collector: FlowCollector<T>) { val slot = allocateSlot() try { if (collector is SubscribedFlowCollector) collector.onSubscription() val collectorJob = currentCoroutineContext()[Job] var oldState: Any? = null // previously emitted T!! | NULL (null -- nothing emitted yet) // The loop is arranged so that it starts delivering current value without waiting first while (true) { // Here the coroutine could have waited for a while to be dispatched, // so we use the most recent state here to ensure the best possible conflation of stale values val newState = _state.value // always check for cancellation collectorJob?.ensureActive() // Conflate value emissions using equality if (oldState == null || oldState != newState) { collector.emit(NULL.unbox(newState)) oldState = newState } // Note: if awaitPending is cancelled, then it bails out of this loop and calls freeSlot if (!slot.takePending()) { // try fast-path without suspending first slot.awaitPending() // only suspend for new values when needed } } } finally { freeSlot(slot) } }
StateFlowSlot SharedFlowSlot
每一个collector都分配了一个flowSlot,用于记录collector的状态。 核心是这行:collector.emit(NULL.unbox(newState)) 我们最开始传入的函数就拿到了最新的值,然后执行方法。
所以从本质来看,抛去所有有的没的,flow的本质是这样的: 有一个值需要被观察,我们把这个值封装到一个对象中,然后观察者可以注册,当值变更的时候,通知观察者。 就是一个非常简单的观察者模式,但是结合了协程,以及各种状态维护,让整个源码看起来晦涩难懂。
但是如果只是一个观察者模式,也不知道大张旗鼓的封装如此多的东西,首先要解决观察者模式最大的问题。
线程问题,所以把collect设置为suspend函数,然后flow本身就可以切换线程做任务,同时不阻塞当前线程。
顺便过一下flow的核心点:
flow("1").collect{print(it)}
flow("1") ----> 只是构建了一个对象,还没有执行任何函数。 调用collect()才真正开始执行,最终触发了
private class SafeFlow<T>(private val block: suspend FlowCollector<T>.() -> Unit) : AbstractFlow<T>() {
override suspend fun collectSafely(collector: FlowCollector<T>) {
collector.block()
}
}
public suspend inline fun <T> Flow<T>.collect(crossinline action: suspend (value: T) -> Unit): Unit =
collect(object : FlowCollector<T> {
override suspend fun emit(value: T) = action(value)
})
这个block()即flow声明的那个函数,执行了emit()函数。
private fun emit(uCont: Continuation<Unit>, value: T): Any? {
val currentContext = uCont.context
currentContext.ensureActive()
// This check is triggered once per flow on happy path.
val previousContext = lastEmissionContext
if (previousContext !== currentContext) {
checkContext(currentContext, previousContext, value)
}
completion = uCont
return emitFun(collector as FlowCollector<Any?>, value, this as Continuation<Unit>)
}
触发emitFun最后触发了 “action(value)”,这个 “action(value)”就是collect{}里面的函数。