强制SharedFlow发送事件绑定可用生命周期

46 阅读1分钟

准备需要的类与方法

private class ScopeLifecycleFlowImpl<T : ScopeLifecycle>(
    private val lifecycle: Lifecycle,
    private val upstream: Flow<T>,
) : Flow<T> {
    override suspend fun collect(collector: FlowCollector<T>) {
        var lastEvent: Lifecycle.Event = Lifecycle.Event.ON_CREATE
        val observer = LifecycleEventObserver { _, event ->
            lastEvent = event
        }
        lifecycle.addObserver(observer)
        try {
            upstream.collect { value ->
                val minActiveEvent = value.minActiveEvent
                val maxActiveEvent = value.maxActiveEvent
                require(minActiveEvent != Lifecycle.Event.ON_ANY && maxActiveEvent != Lifecycle.Event.ON_ANY) {
                    "minActiveEvent and maxActiveEvent cannot be ON_ANY."
                }
                require(minActiveEvent <= maxActiveEvent) {
                    "minActiveEvent cannot be greater than maxActiveEvent."
                }
                if (lastEvent in (minActiveEvent..maxActiveEvent)) {
                    collector.emit(value)
                }
            }
        } finally {
            lifecycle.removeObserver(observer)
        }
    }
}

fun <T : ScopeLifecycle> Flow<T>.scopeLifecycle(
    lifecycle: Lifecycle,
): Flow<T> {
    return ScopeLifecycleFlowImpl(lifecycle, this)
}

interface ScopeLifecycle {
    val minActiveEvent: Lifecycle.Event
    val maxActiveEvent: Lifecycle.Event
}

interface IUiEffect<T> : ScopeLifecycle

data class UiEffect<T>(
    val data: T,
    override val minActiveEvent: Lifecycle.Event,
    override val maxActiveEvent: Lifecycle.Event
) : IUiEffect<T>

viewmodel中声明

private val _uiEffectFlow = MutableSharedFlow<UiEffect<String>>()
val uiEffectFlow = _uiEffectFlow.asSharedFlow()

fun sendEffect(
    data: String,
    minActiveEvent: Lifecycle.Event = Lifecycle.Event.ON_CREATE,
    maxActiveEvent: Lifecycle.Event = Lifecycle.Event.ON_RESUME
) {
    viewModelScope.launch {
        _uiEffectFlow.emit(UiEffect(data, minActiveEvent, maxActiveEvent))
    }
}

activity中使用

lifecycleScope.launch {
    model.uiEffectFlow.scopeLifecycle(lifecycle).collect {
    }
}
lifecycleScope.launch {
    for (i in 0..10) {
        model.sendEffect(i.toString())
        delay(3000)
    }
}