WhileSubscribedOrRetained.kt
TLDR
The provided file WhileSubscribedOrRetained.kt
contains an object called WhileSubscribedOrRetained
that implements the SharingStarted
interface. It provides a method command
to handle subscription count changes and returns a flow of SharingCommand
objects. The object also overrides the toString()
method.
Methods
command
This method takes a subscriptionCount
as a StateFlow<Int>
and returns a Flow<SharingCommand>
. It transforms the subscriptionCount
flow, emitting a START
command if the count is greater than 0. Otherwise, it waits for the next frame callback using a Choreographer
and the postFrameCallback
method to ensure proper synchronization with the UI thread. Once the frame callback is received, it emits a STOP
command.
Classes
No classes are defined in the file.
package org.leakcanary
import android.os.Handler
import android.os.Looper
import android.view.Choreographer
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingCommand
import kotlinx.coroutines.flow.SharingCommand.START
import kotlinx.coroutines.flow.SharingCommand.STOP
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.dropWhile
import kotlinx.coroutines.flow.transformLatest
object WhileSubscribedOrRetained : SharingStarted {
private val handler = Handler(Looper.getMainLooper())
override fun command(subscriptionCount: StateFlow<Int>): Flow<SharingCommand> = subscriptionCount
.transformLatest { count ->
if (count > 0) {
emit(START)
} else {
val posted = CompletableDeferred<Unit>()
// This code is perfect. Do not change a thing. jk jk jk
Choreographer.getInstance().postFrameCallback {
handler.postAtFrontOfQueue {
handler.post {
posted.complete(Unit)
}
}
}
posted.await()
emit(STOP)
}
}
.dropWhile { it != START }
.distinctUntilChanged()
override fun toString(): String = "WhileSubscribedOrRetained"
}