mirror of
				https://github.com/InsanusMokrassar/MicroUtils.git
				synced 2025-11-04 06:00:22 +00:00 
			
		
		
		
	SpecialMutableStateFlow : MutableStateFlow
This commit is contained in:
		@@ -3,6 +3,7 @@
 | 
			
		||||
## 0.20.18
 | 
			
		||||
 | 
			
		||||
* `Coroutines`:
 | 
			
		||||
    * `SpecialMutableStateFlow` now extends `MutableStateFlow`
 | 
			
		||||
    * `Compose`:
 | 
			
		||||
        * Deprecate `FlowState` due to its complexity in fixes
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,7 @@
 | 
			
		||||
package dev.inmo.micro_utils.coroutines.compose
 | 
			
		||||
 | 
			
		||||
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.doInUI
 | 
			
		||||
import kotlinx.coroutines.CoroutineScope
 | 
			
		||||
import kotlinx.coroutines.Dispatchers
 | 
			
		||||
 | 
			
		||||
@@ -26,9 +23,9 @@ class FlowState<T>(
 | 
			
		||||
            tryEmit(value)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    override suspend fun onChange(value: T) {
 | 
			
		||||
    override fun onChangeWithoutSync(value: T) {
 | 
			
		||||
        internalValue = value
 | 
			
		||||
        super.onChange(value)
 | 
			
		||||
        super.onChangeWithoutSync(value)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun component1(): T = value
 | 
			
		||||
 
 | 
			
		||||
@@ -3,10 +3,14 @@ package dev.inmo.micro_utils.coroutines
 | 
			
		||||
import kotlinx.coroutines.CoroutineScope
 | 
			
		||||
import kotlinx.coroutines.Dispatchers
 | 
			
		||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
 | 
			
		||||
import kotlinx.coroutines.InternalCoroutinesApi
 | 
			
		||||
import kotlinx.coroutines.channels.BufferOverflow
 | 
			
		||||
import kotlinx.coroutines.flow.FlowCollector
 | 
			
		||||
import kotlinx.coroutines.flow.MutableSharedFlow
 | 
			
		||||
import kotlinx.coroutines.flow.MutableStateFlow
 | 
			
		||||
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
 | 
			
		||||
@@ -15,7 +19,9 @@ import kotlinx.coroutines.flow.StateFlow
 | 
			
		||||
open class SpecialMutableStateFlow<T>(
 | 
			
		||||
    initialValue: T,
 | 
			
		||||
    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(
 | 
			
		||||
        replay = 0,
 | 
			
		||||
        extraBufferCapacity = 2,
 | 
			
		||||
@@ -28,16 +34,37 @@ open class SpecialMutableStateFlow<T>(
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    protected var _value: T = initialValue
 | 
			
		||||
    override val value: T
 | 
			
		||||
    @OptIn(InternalCoroutinesApi::class)
 | 
			
		||||
    override var value: T
 | 
			
		||||
        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
 | 
			
		||||
        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) {
 | 
			
		||||
        if (_value != it) {
 | 
			
		||||
            onChange(it)
 | 
			
		||||
        }
 | 
			
		||||
        doOnChangeAction(it)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override val replayCache: List<T>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user