SpecialMutableStateFlow : MutableStateFlow

This commit is contained in:
InsanusMokrassar 2023-12-04 15:37:02 +06:00
parent f3f9920bfb
commit 43e782ab6f
3 changed files with 37 additions and 12 deletions

View File

@ -3,6 +3,7 @@
## 0.20.18 ## 0.20.18
* `Coroutines`: * `Coroutines`:
* `SpecialMutableStateFlow` now extends `MutableStateFlow`
* `Compose`: * `Compose`:
* Deprecate `FlowState` due to its complexity in fixes * Deprecate `FlowState` due to its complexity in fixes

View File

@ -1,10 +1,7 @@
package dev.inmo.micro_utils.coroutines.compose package dev.inmo.micro_utils.coroutines.compose
import androidx.compose.runtime.MutableState import androidx.compose.runtime.MutableState
import androidx.compose.runtime.State
import androidx.compose.runtime.derivedStateOf
import dev.inmo.micro_utils.coroutines.SpecialMutableStateFlow import dev.inmo.micro_utils.coroutines.SpecialMutableStateFlow
import dev.inmo.micro_utils.coroutines.doInUI
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -26,9 +23,9 @@ class FlowState<T>(
tryEmit(value) tryEmit(value)
} }
override suspend fun onChange(value: T) { override fun onChangeWithoutSync(value: T) {
internalValue = value internalValue = value
super.onChange(value) super.onChangeWithoutSync(value)
} }
override fun component1(): T = value override fun component1(): T = value

View File

@ -3,10 +3,14 @@ package dev.inmo.micro_utils.coroutines
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.InternalCoroutinesApi
import kotlinx.coroutines.channels.BufferOverflow import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.flow.FlowCollector import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.internal.SynchronizedObject
import kotlinx.coroutines.internal.synchronized
/** /**
* Works like [StateFlow], but guarantee that latest value update will always be delivered to * Works like [StateFlow], but guarantee that latest value update will always be delivered to
@ -15,7 +19,9 @@ import kotlinx.coroutines.flow.StateFlow
open class SpecialMutableStateFlow<T>( open class SpecialMutableStateFlow<T>(
initialValue: T, initialValue: T,
internalScope: CoroutineScope = CoroutineScope(Dispatchers.Default) internalScope: CoroutineScope = CoroutineScope(Dispatchers.Default)
) : StateFlow<T>, FlowCollector<T>, MutableSharedFlow<T> { ) : MutableStateFlow<T>, FlowCollector<T>, MutableSharedFlow<T> {
@OptIn(InternalCoroutinesApi::class)
private val syncObject = SynchronizedObject()
protected val internalSharedFlow: MutableSharedFlow<T> = MutableSharedFlow( protected val internalSharedFlow: MutableSharedFlow<T> = MutableSharedFlow(
replay = 0, replay = 0,
extraBufferCapacity = 2, extraBufferCapacity = 2,
@ -28,16 +34,37 @@ open class SpecialMutableStateFlow<T>(
) )
protected var _value: T = initialValue protected var _value: T = initialValue
override val value: T @OptIn(InternalCoroutinesApi::class)
override var value: T
get() = _value get() = _value
protected open suspend fun onChange(value: T) { set(value) {
doOnChangeAction(value)
}
@OptIn(InternalCoroutinesApi::class)
override fun compareAndSet(expect: T, update: T): Boolean {
return synchronized(syncObject) {
if (expect == _value && update != _value) {
doOnChangeAction(update)
}
expect == _value
}
}
protected open fun onChangeWithoutSync(value: T) {
_value = value _value = value
publicSharedFlow.emit(value) publicSharedFlow.tryEmit(value)
}
@OptIn(InternalCoroutinesApi::class)
protected open fun doOnChangeAction(value: T) {
synchronized(syncObject) {
if (_value != value) {
onChangeWithoutSync(value)
}
}
} }
protected val job = internalSharedFlow.subscribe(internalScope) { protected val job = internalSharedFlow.subscribe(internalScope) {
if (_value != it) { doOnChangeAction(it)
onChange(it)
}
} }
override val replayCache: List<T> override val replayCache: List<T>