2
votes

I am trying to implement kotlin stateflow, but not able to know the reason why it is not working.

Current output: verificatio 34567

Expected Output: verificatio 34567 verificatio failed

package stateflowDuplicate

import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
val firebasePhoneVerificationListener = FirebaseOTPVerificationOperation1()
val oTPVerificationViewModal = OTPVerificationViewModal1(firebasePhoneVerificationListener)
oTPVerificationViewModal.fail()
}

class OTPVerificationViewModal1(private val firebasePhoneVerificationListener: FirebaseOTPVerificationOperation1) {

init {
    startPhoneNumberVerification()
    setUpListener()
}

 suspend fun fail(){
    firebasePhoneVerificationListener.fail()
}

private fun startPhoneNumberVerification() {
    firebasePhoneVerificationListener.initiatePhoneVerification("34567")
}

private fun setUpListener() {
    runBlocking {
        firebasePhoneVerificationListener.phoneVerificationFailed.collect {
            println("verificatio $it")
        }
    }
}

}

Second class
package stateflowDuplicate

import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.runBlocking

class FirebaseOTPVerificationOperation1 {

private val _phoneVerificationFailed = MutableStateFlow<String?>(null)
val phoneVerificationFailed: StateFlow<String?>
    get() = _phoneVerificationFailed

  fun initiatePhoneVerification(phoneNumber: String) {
         _phoneVerificationFailed.value = phoneNumber
}
 suspend fun fail() {
     delay(200L)
    _phoneVerificationFailed.value = "failed"
}

}

Tried to understand the concept from these links, Link1 Link2

1

1 Answers

2
votes

You have to start a new coroutine to call collect because the coroutine will keep collecting values until its Job gets cancelled. Don't use runBlocking builder for that, use launch builder instead:

private fun setUpListener() = launch {
    firebasePhoneVerificationListener.phoneVerificationFailed.collect {
        println("verificatio $it")
    }
}

Now to make it work you need to implement CoroutineScope interface in your class. You can do it like this:

class OTPVerificationViewModal1(
    private val firebasePhoneVerificationListener: FirebaseOTPVerificationOperation1
): CoroutineScope by CoroutineScope(Dispatchers.Default) {
    ...
}

If you run it now you will get this output:

verificatio 34567
verificatio failed