Rep*_*tor 14 kotlin kotlin-coroutines kotlin-coroutines-flow kotlin-coroutine-channel
这是我的 FirebaseOTPVerificationOperation 类,其中定义了我的 MutableStateFlow 属性,并更改了值,
    @ExperimentalCoroutinesApi
class FirebaseOTPVerificationOperation @Inject constructor(
    private val activity: Activity,
    val logger: Logger
) {
    private val _phoneAuthComplete = MutableStateFlow<PhoneAuthCredential?>(null)
    val phoneAuthComplete: StateFlow<PhoneAuthCredential?>
        get() = _phoneAuthComplete
    private val _phoneVerificationFailed = MutableStateFlow<String>("")
    val phoneVerificationFailed: StateFlow<String>
        get() = _phoneVerificationFailed
    private val _phoneCodeSent = MutableStateFlow<Boolean?>(null)
    val phoneCodeSent: StateFlow<Boolean?>
        get() = _phoneCodeSent
    private val _phoneVerificationSuccess = MutableStateFlow<Boolean?>(null)
    val phoneVerificationSuccess: StateFlow<Boolean?>
        get() = _phoneVerificationSuccess
    fun resendPhoneVerificationCode(phoneNumber: String) {
        _phoneVerificationFailed.value = "ERROR_RESEND"
    }
}
Run Code Online (Sandbox Code Playgroud)
这是我的视图模式,我在那里监听 stateflow 属性的变化,如下所示,
class OTPVerificationViewModal @AssistedInject constructor(
    private val coroutinesDispatcherProvider: AppCoroutineDispatchers,
    private val firebasePhoneVerificationListener: FirebaseOTPVerificationOperation,
    @Assisted private val savedStateHandle: SavedStateHandle
) : ViewModel() {
    @AssistedInject.Factory
    interface Factory {
        fun create(savedStateHandle: SavedStateHandle): OTPVerificationViewModal
    }
    val phoneAuthComplete = viewModelScope.launch {
        firebasePhoneVerificationListener.phoneAuthComplete.filter {
            Log.e("1","filter auth $it")
            it.isNotNull()
        }.collect {
            Log.e("2","complete auth $it")
        }
    }
    val phoneVerificationFailed = viewModelScope.launch {
        firebasePhoneVerificationListener.phoneVerificationFailed.filter {
            Log.e("3","filter failed $it")
            it.isNotEmpty()
        }.collect {
            Log.e("4","collect failed $it")
        }
    }
    val phoneCodeSent = viewModelScope.launch {
        firebasePhoneVerificationListener.phoneCodeSent.filter {
            Log.e("5","filter code $it")
            it.isNotNull()
        }.collect {
            Log.e("6","collect code $it")
        }
    }
    val phoneVerificationSuccess = viewModelScope.launch {
        firebasePhoneVerificationListener.phoneVerificationSuccess.filter {
            Log.e("7","filter success $it")
            it.isNotNull()
        }.collect {
            Log.e("8","collect success $it")
        }
    }
    init {
        resendVerificationCode()
        secondCall()
    }
    private fun secondCall() {
        viewModelScope.launch(coroutinesDispatcherProvider.io) {
            delay(10000)
            resendVerificationCode()
        }
    }
    fun resendVerificationCode() {
        viewModelScope.launch(coroutinesDispatcherProvider.io) {
            firebasePhoneVerificationListener.resendPhoneVerificationCode(
                getNumber()
            )
        }
    }
    private fun getNumber() =
            "+9191111116055"
}
Run Code Online (Sandbox Code Playgroud)
问题是
firebasePhoneVerificationListener.phoneVerificationFailed在第一次调用时在视图模式中触发,
init {
        resendVerificationCode()
    }
但是对于 , 的第二次调用init {
        secondCall()
    },
firebasePhoneVerificationListener.phoneVerificationFailed在 viewmodal 中没有被触发,我不知道为什么会发生这种情况,任何原因或解释都会非常有用。
电流输出:
filter auth null
filter failed 
filter code null
filter success null
filter failed ERROR_RESEND
collect failed ERROR_RESEND
预期输出:
filter auth null
filter failed 
filter code null
filter success null
filter failed ERROR_RESEND
collect failed ERROR_RESEND
filter failed ERROR_RESEND
collect failed ERROR_RESEND
Вла*_*нин 29
StateFlow 是 SharedFlow: https ://github.com/Kotlin/kotlinx.coroutines/issues/2034
我的文章中有更详细的描述:https://veldan1202.medium.com/kotlin-setup-sharedflow-31debf613b91
val shared = MutableSharedFlow(
    replay = 1,
    onBufferOverflow = BufferOverflow.DROP_OLDEST,
)
shared.tryEmit(value)
Run Code Online (Sandbox Code Playgroud)
        小智 9
状态流发出的值被混合并且不会两次发出相同的连续结果,您可以认为好像条件检查正在验证旧的发出值不等于新发出的值。
当前输出:filter auth null filter failed filter code null filter success null filter failed ERROR_RESEND collect failed ERROR_RESEND
(过滤器失败 ERROR_RESEND 收集失败 ERROR_RESEND)这是与发出的旧值相同的值,因此您不会看到它们被发出。
使用 a Channel:这会在两次发送相同的值后发出。
将此添加到您的 ViewModel
val _intent = Channel(Channel.CONFLATED)
使用send/放置值trySend
_intent.send(intentLocal)
观察流动
_intent.consumeAsFlow().collect { // 做某事 }
Pankaj 的答案是正确的,StateFlow不会两次发出相同的值。正如文档所暗示的那样:
状态流中的值以
Any.equals与distinctUntilChanged运算符类似的方式使用比较进行合并。它用于将传入的更新合并到valueinMutableStateFlow并在新值等于先前发出的值时抑制将值发射到收集器。
因此,要解决此问题,您可以创建一个包装类并覆盖equals(and hashCode) 方法以返回,false即使这些类实际上是相同的:
sealed class VerificationError {
    object Resend: VerificationError()
    override fun equals(other: Any?): Boolean {
        return false
    }
    override fun hashCode(): Int {
        return Random.nextInt()
    }
}
Run Code Online (Sandbox Code Playgroud)
        |   归档时间:  |  
           
  |  
        
|   查看次数:  |  
           8666 次  |  
        
|   最近记录:  |