Earlier, I have used this function:
override fun getAuthResponse() = callbackFlow {
val listener = AuthStateListener {
trySend(it.currentUser == null)
}
auth.addAuthStateListener(listener)
awaitClose {
auth.removeAuthStateListener(listener)
}
}
But due to some constraints that are explained here I had to use:
override fun getAuthResponse(): StateFlow<Boolean> {
val flow = MutableStateFlow(auth.currentUser == null)
val listener = AuthStateListener {
flow.value = it.currentUser == null
}
auth.addAuthStateListener(listener)
return flow
}
Which is what I need, but I cannot find awaitClose {...}, so I can remove the listener. How to remove the listener when using StateFlow?
CodePudding user response:
You can use your callback flow with stateIn
to turn it into a StateFlow that only uses a listener when it has collector(s). When it loses all collectors, WhileSubscribed causes the upstream callback flow to terminate, so it will remove the listener. When it gets a new first collector, it restarts the upstream flow from scratch.
To use stateIn
, you must have a coroutine scope available to run the state flow conversion in. I'm just using GlobalScope for this example. If this is in a ViewModel you might want to use viewModelScope
instead. Or you could make the coroutine scope an input parameter of the function. I think GlobalScope is probably OK due to the use of WhileSubscribed()
.
override fun getAuthResponse(): StateFlow<Boolean> = callbackFlow {
send(it.currentUser == null)
val listener = AuthStateListener {
trySend(it.currentUser == null)
}
auth.addAuthStateListener(listener)
awaitClose {
auth.removeAuthStateListener(listener)
}
}.stateIn(GlobalScope, SharingStarted.WhileSubscribed(), auth.currentUser == null)