Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

394
Views
MutableStateFlow no emite valores después de la primera emisión de kotlin coroutine

Esta es mi clase FirebaseOTPVerificationOperation, donde se definen mis propiedades MutableStateFlow y se cambian los valores,

 @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" } }

Esta es mi vista modal, desde donde escucho los cambios en las propiedades del flujo de estado, de la siguiente manera,

 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" }

el problema es que

 firebasePhoneVerificationListener.phoneVerificationFailed

es despedido en viewmodal para la primera llamada de,

 init { resendVerificationCode() }

pero para segunda llamada de:

 init { secondCall() }

firebasePhoneVerificationListener.phoneVerificationFailed no se dispara en viewmodal, no sé por qué sucedió, cualquier razón o explicación será muy apreciada.

Salida de corriente:

 filter auth null filter failed filter code null filter success null filter failed ERROR_RESEND collect failed ERROR_RESEND

Rendimiento esperado:

 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
over 4 years ago · Hanz Gallego
8 answers
Answer question

0

Usar un Channel : esto se emite después de enviar el mismo valor dos veces.

  1. Agregue esto a su ViewModel

    val _intent = Canal(Canal.CONFLATED)

  2. Poner valores usando send / trySend

    _intento.send(intentoLocal)

  3. observar como flujo

    _intent.consumeAsFlow().collect { //hacer algo}

over 4 years ago · Hanz Gallego Report

0

El valor emitido por el flujo de estado se fusiona y no emite el mismo resultado consecutivo dos veces, puede pensar como si una verificación de condición validara que el valor emitido anterior no es igual al valor emitido recientemente.

Salida actual: filtro de autenticación nulo filtro fallido código de filtro nulo filtro correcto nulo filtro fallido ERROR_RESEND recopilación fallida ERROR_RESEND

(el filtro falló ERROR_RESEND, la recopilación falló ERROR_RESEND) Este es el mismo valor anterior que se emitió, por lo que no verá que se emitan.

over 4 years ago · Hanz Gallego Report

0

La respuesta de Pankaj es correcta, StateFlow no emitirá el mismo valor dos veces. Como sugiere la documentación :

Los valores en el flujo de estado se fusionan mediante la comparación Any.equals de forma similar al operador distinctUntilChanged . Se usa para fusionar las actualizaciones entrantes con el value en MutableStateFlow y para suprimir la emisión de los valores a los recopiladores cuando el nuevo valor es igual al emitido anteriormente.

Por lo tanto, para resolver este problema, puede crear una clase envolvente y anular el método equals (y hashCode ) para devolver false incluso si las clases son de hecho las mismas:

 sealed class VerificationError { object Resend: VerificationError() override fun equals(other: Any?): Boolean { return false } override fun hashCode(): Int { return Random.nextInt() } }
over 4 years ago · Hanz Gallego Report

0

Tuve un problema similar después de fusionar las transmisiones. La función emit() no se ejecutará si == se usa para determinar la igualdad.

La forma de resolver el problema: puede envolver una capa y reescribir los métodos hashCode() y equals(). El método equals() devuelve directamente falso. Esta solución funciona en mi código. La corriente después de la combinación también ha cambiado.

La respuesta de Pankaj es correcta, StateFlow no emitirá el mismo valor dos veces.

Antes de envolver, el resultado de == sigue siendo verdadero incluso si el contenido es diferente.

over 4 years ago · Hanz Gallego Report

0

Creo que tengo una comprensión más profunda de este problema. Lo primero que debe asegurarse es que para StateFlow, no se recomienda utilizar tipos de colección de variables (como MutableList, etc.). Porque MutableList no es seguro para subprocesos. Si hay varias referencias en el código central, puede que el programa se bloquee.

Antes, el método que usaba era ajustar la clase y anular el método equals. Sin embargo, creo que esta solución no es el método más seguro. La forma más segura es para la copia profunda, Kotlin proporciona los métodos toMutableList() y toList() que son ambos de copia profunda. El método emit juzga si hay un cambio dependiendo de si el resultado de equals() es igual.

La razón por la que tengo este problema es que el tipo de datos que usa emit() es: SparseArray<MutableList>. StateFlow llama al método equals para SparseArray. Cuando cambia MutableList, el resultado de equals no cambia en este momento (incluso si cambian los métodos equals y hashcode de MutableList).

Finalmente, cambié el tipo a SparseArray<List>. Aunque la pérdida de rendimiento causada por agregar y eliminar datos, esto también resuelve el problema fundamentalmente.

over 4 years ago · Hanz Gallego Report

0

Como se mencionó anteriormente, LiveData emite datos cada vez, mientras que StateFlow emite solo valores diferentes. TryEmit() no funciona. En mi caso encontré dos soluciones.

  1. Si tiene datos de String , puede emitir nuevamente de esta manera:

     private fun emitNewValue() { subscriber.value += " " subscriber.value.dropLast(1) }

    Para otra clase, puede usar esto (o crear una función de extensión):

     private fun <T> emitNewValue(value: T) { if (subscriber.value == value) { subscriber.value = null } subscriber.value = value }

Pero es una forma mala y con errores (los valores se emiten dos veces adicionalmente).

  1. Intente encontrar todos los suscriptores que cambien sus valores. Puede no ser evidente. Por ejemplo, cambie el foco de escucha, Switch (casilla de verificación). Cuando Switch , un texto también puede cambiar, por lo que debe suscribirse a este oyente. De la misma manera, cuando enfoca otra vista, un texto de error puede cambiar.
over 4 years ago · Hanz Gallego Report

0

StateFlow es SharedFlow: https://github.com/Kotlin/kotlinx.coroutines/issues/2034


 val shared = MutableSharedFlow( replay = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST, ) shared.tryEmit(value)

PD. Vel_daN: Ama lo que HACES 💚.

over 4 years ago · Hanz Gallego Report

0

¡Podría hacer que _phoneVerificationFailed sea anulable y enviar un valor nulo entre las dos llamadas!

over 4 years ago · Hanz Gallego Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!