Search code examples
androidkotlinkotlin-sharedflow

SharedFlow.last() never returns


I have a sharedFlow with a replay value of one. But when I am trying to access the last emitted value, the call never returns (while first() does).

Below is my code:

val game = GameSettingsRepository.gameIdFlow.flatMapLatest { gameId ->
    gameId?.let { gameDataSource.getGame(it) }
        ?: flowOf()
}.shareIn(ProcessLifecycleOwner.get().lifecycleScope, SharingStarted.Eagerly, 1)

where getGame() is a callbackFlow:

override fun getGame(gameId: String): Flow<Game> = callbackFlow {
    val listener = object : ValueEventListener {
        override fun onDataChange(snapshot: DataSnapshot) {
            snapshot.getValue(GameFirebase::class.java)?.let { gameFirebase ->
                    trySend(gameFirebase.toData())
                }
            }
        }

        override fun onCancelled(error: DatabaseError) {
            TODO("Not yet implemented")
        }

    }
    db.child(gameId).addValueEventListener(listener)
    awaitClose { db.child(gameId).removeEventListener(listener) }
}

and so this: val myGame = game.last() never returns anything while val myGame = game.first()does.

Why and How?


Solution

  • A SharedFlow is infinite. It stays open forever awaiting possible future emissions. Therefore, it has no last element.

    The last() function works by collecting an entire Flow and then returning the last result. Since collect() never returns when called on a SharedFlow, last() can never return either. It will suspend forever.