рд╕рднреА рдХреЛ рдирдорд╕реНрдХрд╛рд░редрдХреБрдЫ рджрд┐рдиреЛрдВ рдкрд╣рд▓реЗ, JetBrains рдиреЗ Corutin - 1.3.6 рдХрд╛ рдПрдХ рдирдпрд╛ рд╕рдВрд╕реНрдХрд░рдг рдЬрд╛рд░реА рдХрд┐рдпрд╛ рдерд╛ рдФрд░ рдирд╡рд╛рдЪрд╛рд░реЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдкреНрд░рд╡рд╛рд╣ - StateFlow рдХреА рдирдИ рдЙрдк-рдкреНрд░рдЬрд╛рддрд┐ рдереА, рдЬреЛ рдХрд┐ ConflatedBroadcastChannel рдХреА рдЬрдЧрд╣ рд▓реЗрддреА рд╣реИред рдореИрдВрдиреЗ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдореЗрдВ рд╕реНрдЯреЗрдЯрдлреНрд▓реЛ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рдиреЗ рдФрд░ рдЖрдВрддрд░рд┐рдХ рд╕рдВрд░рдЪрдирд╛ рдХрд╛ рдЕрдзреНрдпрдпрди рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛редрдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдПрдВрдбреНрд░реЙрдЗрдб рдХреЗ рд▓рд┐рдП рдпрд╛ рдПрдордкреАрдкреА рдореЗрдВ рд╡рд┐рдХрд╕рд┐рдд рд╣реЛрдиреЗ рдкрд░ рдХреЛрдЯрд▓рд┐рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдХрдИ рд▓реЛрдЧ рдЗрди рд╢рд░реНрддреЛрдВ рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рд╣реИрдВ, рдЬреЛ рдирд╣реАрдВ рд╣реИрдВ - рдпреЗ рд╕рдВрд╕реНрдерд╛рдПрдВ рдЖрд░рдПрдХреНрд╕рдЬреИрд╡рд╛ рд╕реЗ BehaviorProcessor / BehaviorSubject рдХреЗ рдХрд░реАрдмреА рдПрдирд╛рд▓реЙрдЧ рд╣реИрдВ рдФрд░ рдЬреЗрдЯрдкреИрдХ рд╕реЗ LiveData / MutableLiveDataредStateFlow рд╣реА рдлрд╝реНрд▓реЛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХрд╛ рдПрдХ рд╕рд░рд▓ рд╡рд┐рд╕реНрддрд╛рд░ рд╣реИ рдФрд░ рджреЛ рд░реВрдкреЛрдВ рдореЗрдВ рдЖрддрд╛ рд╣реИ:public interface StateFlow<out T> : Flow<T> {
public val value: T
}
public interface MutableStateFlow<T> : StateFlow<T> {
public override var value: T
}
рдпрд╣ рд╡рд┐рдЪрд╛рд░ LiveData / MutableLiveData рдХреЗ рд╕рдорд╛рди рд╣реИ - рдПрдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдпрд╣ рдХреЗрд╡рд▓ рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рдХреЛ рдкрдврд╝ рд╕рдХрддрд╛ рд╣реИ, рдФрд░ рджреВрд╕рд░реЗ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЗрд╕реЗ рднреА рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИредConflatedBroadcastChannel рдХреА рддреБрд▓рдирд╛ рдореЗрдВ StateFlow рд╣рдореЗрдВ рдХреНрдпрд╛ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ:- рдПрдХ рд╕рд░рд▓ рдФрд░ рдХрдЪрд░рд╛-рдореБрдХреНрдд рдЖрдВрддрд░рд┐рдХ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрдиред
- рдПрдХ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдЖрдЗрдЯрдо рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЕрд╢рдХреНрдд рднреА рд╕рдВрднрд╡ рд╣реИред
- рд░реАрдб-рдУрдирд▓реА рдФрд░ рд░реАрдб-рд░рд╛рдЗрдЯ рдЗрдВрдЯрд░рдлреЗрд╕ рдореЗрдВ рдкреГрдердХреНрдХрд░рдгред
- рд▓рд┐рдВрдХ рдХреА рддреБрд▓рдирд╛ рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп рд╕рдорд╛рдирддрд╛ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рддрддреНрд╡реЛрдВ рдХреА рддреБрд▓рдирд╛ рдХрд░рдирд╛ред
рдЕрдм рд╕реНрдЯреЗрдЯрдлреНрд▓реЛ рдХреЗ рдПрдХ рд╕рд░рд▓ рдЙрдкрдпреЛрдЧ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдПрдХ рдЕрд╢рдХреНрдд рддрддреНрд╡ рдХреЗ рд╕рд╛рде рдХрд┐рд╕реА рднреА рдкреНрд░рдХрд╛рд░ рдХреЛ рд╕реЗрдЯ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рд╡рд╛рд▓рд╛ рдПрдХ рдкреНрд░рд╛рдердорд┐рдХ рдЖрд╡рд░рдг рдмрдирд╛рдпрд╛:class StateFlowRepository<T>(initialValue: T? = null) {
private val stateFlow = MutableStateFlow(initialValue)
var value: T?
get() = stateFlow.value
set(value) {
stateFlow.value = value
}
val stream: Flow<T?> = stateFlow
}
рд╣рдореЗрдВ рдбреЗрдЯрд╛ рдорд┐рд▓рддрд╛ рд╣реИ:lifecycleScope.launch {
simpleRepo.stream.collect {
addData(it.toString())
}
}
рдФрд░ рд╣рдо рд╕реНрдХреНрд░реАрди рдкрд░ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рд╕рд░рд▓ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рд╕рд╛рде рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдЗрд╕рд╕реЗ рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рд╣реЛрддреА рд╣реИ рдФрд░ рд╕рдм рдХреБрдЫ рдШрдбрд╝реА рдХреА рддрд░рд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ:
рдЕрдм рдЖрдЗрдП рдЕрдВрджрд░ рджреЗрдЦреЗрдВ рдФрд░ рджреЗрдЦреЗрдВ рдХрд┐ рдпрд╣ рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИредрдореЗрд░реЗ рдЖрд╢реНрдЪрд░реНрдп рдХреЗ рд▓рд┐рдП, рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдмрд╣реБрдд рд╕рд░рд▓ рд╣реИ рдФрд░ рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдХреЗрд╡рд▓ 316 рд▓рд╛рдЗрдиреЗрдВ рд▓рдЧрддреА рд╣реИрдВ, рдЬрд┐рдирдореЗрдВ рд╕реЗ 25% рдЬрд╛рд╡рджреЛрдХреА рд╣реИрдВредрдФрд░ рдЗрд╕рд▓рд┐рдП, рдореБрдЦреНрдп рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╡рд░реНрдЧ StateFlowImpl рд╡рд░реНрдЧ рд╣реИ:private class StateFlowImpl<T>(initialValue: Any) : SynchronizedObject(), MutableStateFlow<T>, FusibleFlow<T> {
private val _state = atomic(initialValue)
private var sequence = 0
private var slots = arrayOfNulls<StateFlowSlot?>(INITIAL_SIZE)
private var nSlots = 0
private var nextIndex = 0
. . .
}
_state - рд╣рдорд╛рд░реЗ рд░рд╛рдЬреНрдп рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░рдорд╛рдгреБ рд▓рд┐рдВрдХредрдЕрдиреБрдХреНрд░рдо - рдПрдХ рд╕рд╣рд╛рдпрдХ рд╕рдВрдХреЗрддрдХ, рдЬреЛ, рд╕рдорддрд╛ / рд╡рд┐рд╖рдорддрд╛ рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рд░рд╛рдЬреНрдпрд╕реНрд▓реЙрдЯреНрд╕ рдХреЛ рдЕрджреНрдпрддрди рдХрд░рдиреЗ рдХреА рд╡рд░реНрддрдорд╛рди рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдкрд░ рд░рд┐рдкреЛрд░реНрдЯ рдХрд░рддрд╛ рд╣реИ - рд╕рд░рдгреА / рдкреВрд▓ StateFlowSlotред StateFlowSlot - StateFlow рдХреЗ рд▓рд┐рдП рдкреНрд░рддреНрдпреЗрдХ "рдХрдиреЗрдХреНрд╢рди" рдХреЗ рд╕рд╣рд╛рдпрдХ рдЕрдореВрд░реНрддредnSlots, nextIndex - рдПрдХреНрд╕реНрдЯреЗрдВрд╕рд┐рдмрд▓ рдПрд░реЗ рд╕реНрд▓реЙрдЯреНрд╕ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реЗрд▓реНрдкрд░ рд╡реИрд░рд┐рдПрдмрд▓рдЪрд▓реЛ рдкрд╣рд▓реЗ рд╕реЗ рд╕реНрдЯреЗрдЯрдлреНрд▓реЛрд╕реНрд▓реЗрдЯ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред рд╡рд╣ рдХреЗрд╡рд▓ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддрд╛ рд╣реИ:private val _state = atomic<Any?>(null)
рд╕реНрд▓реЙрдЯ рд░рд╛рдЬреНрдпреЛрдВ рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд▓рд╕ рддрд░реАрдХреЗредрдкреНрд░рддреНрдпреЗрдХ рд╕реНрд▓реЙрдЯ рд░рд╛рдЬреНрдпреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдореЗрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ:рдЕрд╢рдХреНрдд - рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЙрдирдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВрдХреЛрдИ рдирд╣реАрдВ - рдкреНрд░рдпреБрдХреНрдд рдХрд▓реЗрдХреНрдЯрд░рд▓рдВрдмрд┐рдд рд╕реНрдерд┐рддрд┐ - рдХрд▓реЗрдХреНрдЯрд░ рдХреЛ рдПрдХ рдирдпрд╛ рдорд╛рди рднреЗрдЬрдиреЗ рдХреА рдкреНрд░рддреНрдпрд╛рд╢рд╛ рдореЗрдВCancellableContinuationImpl - рдЧрдВрддрд╡реНрдп рдХреЛ рд▓рдВрдмрд┐рдд рд╕реНрдерд┐рддрд┐ рдореЗрдВ saspended рд░рд╛рдЬреНрдп рдкрд╛рд╕, рдХрд▓реЗрдХреНрдЯрд░ рдирд┐рд▓рдВрдмрд┐рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВ Stateflow рдореЗрдВ рдПрдХ рдирдП рд░рд╛рдЬреНрдп рдореЗрдВ рдЬрдм рддрдХ рдирд╣реАрдВ рдЖрдПрдЧрд╛редрд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ рдХрд┐ рдЬрдм рдЖрдк рдПрдХ рдирдпрд╛ рдорд╛рди рд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВ рддреЛ рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИ:public override var value: T
get() = NULL.unbox(_state.value)
set(value) {
var curSequence = 0
var curSlots: Array<StateFlowSlot?> = this.slots
val newState = value ?: NULL
synchronized(this) {
val oldState = _state.value
if (oldState == newState) return
_state.value = newState
curSequence = sequence
if (curSequence and 1 == 0) {
curSequence++
sequence = curSequence
} else {
sequence = curSequence + 2
return
}
curSlots = slots
}
while (true) {
for (col in curSlots) {
col?.makePending()
}
synchronized(this) {
if (sequence == curSequence) {
sequence = curSequence + 1
return
}
curSequence = sequence
curSlots = slots
}
}
}
рдпрд╣рд╛рдБ рдореБрдЦреНрдп рдХрд╛рд░реНрдп рдлреНрд▓реЛрдХреЛрд▓реЗрдХреНрдЯрд░ рдХреЗ рд▓рд┐рдП рд▓рдЧрд╛рддрд╛рд░ рдХреЙрд▓ рдХреЗ рд▓рд┐рдП рдЕрд▓рдЧ-рдЕрд▓рдЧ рдкреНрд░рд╡рд╛рд╣ рд╕реЗ StateFlow рд░рд╛рдЬреНрдп рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЛ рдареАрдХ рдХрд░рдирд╛ рд╣реИредрдХрдИ рдЪрд░рдгреЛрдВ рдХреЛ рдкреНрд░рддрд┐рд╖реНрдард┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:- рдирдпрд╛ рдорд╛рди рд╕реЗрдЯ рдХрд░рдирд╛ред
- рдЕрдиреБрдХреНрд░рдо рдорд╛рд░реНрдХрд░ рдХреЛ рд╡рд┐рд╖рдо рдорд╛рди рдкрд░ рд╕реЗрдЯ рдХрд░рдиреЗ рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рд╣рдо рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рд╣реИрдВред
- makePending () - рд╕рднреА рд╕реНрд▓реЙрдЯ рд╕реНрдЯреЗрдЯреНрд╕ (рдпрд╛рдиреА, рд╕рднреА рдХрдиреЗрдХреНрд╢рди) рдХреЛ PENDING рдореЗрдВ рд╕реЗрдЯ рдХрд░рдирд╛ - рд╣рдо рдЬрд▓реНрдж рд╣реА рдПрдХ рдирдпрд╛ рдорд╛рди рднреЗрдЬреЗрдВрдЧреЗред
- рд▓реВрдк рдЕрдиреБрдХреНрд░рдо == рдЙрддреНрд╕реБрдХрддрд╛ рдХреА рдЬрд╛рдВрдЪ рдХрд░рддрд╛ рд╣реИ рдХрд┐ рд╕рднреА рдХрд╛рд░реНрдп рдкреВрд░реЗ рд╣реЛ рдЪреБрдХреЗ рд╣реИрдВ рдФрд░ рдЕрдиреБрдХреНрд░рдо рдХреЛ рдПрдХ рд╕рдо рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рд╕реЗрдЯ рдХрд░рддрд╛ рд╣реИред
рд╕рдВрдЧреНрд░рд╣
рд╡рд┐рдзрд┐ рдореЗрдВ рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИ :override suspend fun collect(collector: FlowCollector<T>) {
val slot = allocateSlot()
var prevState: Any? = null
try {
while (true) {
val newState = _state.value
if (prevState == null || newState != prevState) {
collector.emit(NULL.unbox(newState))
prevState = newState
}
if (!slot.takePending()) {
slot.awaitPending()
}
}
} finally {
freeSlot(slot)
}
}
рдореБрдЦреНрдп рдХрд╛рд░реНрдп рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдорд╛рди рднреЗрдЬрдирд╛ рдФрд░ рдирдП рдореВрд▓реНрдпреЛрдВ рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рдирд╛ рд╣реИ:- рд╣рдо рдПрдХ рдирдП рдХрдиреЗрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реНрд▓реЙрдЯ рдмрдирд╛рддреЗ рд╣реИрдВ рдпрд╛ рдЙрд╕рдХрд╛ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред
- рд╣рдо рдЕрд╢рдХреНрдд рдпрд╛ рд░рд╛рдЬреНрдп рдкрд░рд┐рд╡рд░реНрддрди рдХреЗ рд▓рд┐рдП рд░рд╛рдЬреНрдп рдХреА рдЬрд╛рдБрдЪ рдХрд░рддреЗ рд╣реИрдВред рдПрдорд┐рдЯреАрдо рдПрдХ рдирдпрд╛ рдЕрд░реНрде рд╣реИред
- рд╣рдо рдЬрд╛рдВрдЪрддреЗ рд╣реИрдВ рдХрд┐ рдХреНрдпрд╛ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрд▓реЙрдЯ рддреИрдпрд╛рд░ рд╣реИрдВ (PENDING рд░рд╛рдЬреНрдп) рдФрд░ рдпрджрд┐ рдирд╣реАрдВ, рддреЛ рд╣рдо рдирдП рдореВрд▓реНрдпреЛрдВ рдХреА рдкреНрд░рддреНрдпрд╛рд╢рд╛ рдореЗрдВ рд╕реНрд▓реЙрдЯ рдХреЛ рдирд┐рд▓рдВрдмрд┐рдд рдХрд░ рджреЗрддреЗ рд╣реИрдВред
рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рдпрд╣ рд╕рдм рд╣реИред рд╣рдордиреЗ рдпрд╣ рдирд╣реАрдВ рд╕реЛрдЪрд╛ рдХрд┐ рд╕реНрд▓реЙрдЯреНрд╕ рдХрд╛ рдЖрд╡рдВрдЯрди рдФрд░ рдЙрдирдХреЗ рд░рд╛рдЬреНрдпреЛрдВ рдХрд╛ рдкрд░рд┐рд╡рд░реНрддрди рдХреИрд╕реЗ рд╣реЛрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рд▓рдЧрд╛ рдХрд┐ рдпрд╣ рд╕реНрдЯреЗрдЯрдлреНрд▓реЛ рдХреА рд╕рдордЧреНрд░ рддрд╕реНрд╡реАрд░ рдХреЗ рд▓рд┐рдП рдорд╣рддреНрд╡рдкреВрд░реНрдг рдирд╣реАрдВ рд╣реИредрдзрдиреНрдпрд╡рд╛рджред