How can you emulate `ContentLoadingProgressBar`’s ...
# coroutines
z
How can you emulate `ContentLoadingProgressBar`’s behavior in a
Flow<T>
? Specifically, if I begin observing a
Flow<ViewState>
and it emits no
ViewState.Loaded
in the first 300ms, I want to emit a
ViewState.Loading
while ensuring that this
ViewState.Loading
emits before any
ViewState.Loaded
from the source
Flow<ViewState>
? Kind of equivalent to:
Copy code
val sourceFlow: Flow<ViewState> = ..

sourceFlow
  .onStart {
    delay(300)
    // if `sourceFlow` has not emitted any items yet
    emit(ViewState.Loading)
  }
https://developer.android.com/reference/androidx/core/widget/ContentLoadingProgressBar
l
You cannot use
onStart
for this. You want to race a timer against a flow, so you'll need concurrency, which can be done in
channelFlow
where you can forward the source flow to the channel, and keep the timer running while this is started (until your timer/delay elapses of course).
If you have a great name for an operator like you want, please tell me
u
Dont know flow but
Copy code
Observable.merge(
    Observable.just(Loading),
    actualStream)
    .switchMap { 
        if it is Loading Observable.timer(someDelay).map { it }     
        else Observable.just(it)
e
Copy code
sourceFlow
    .onStart { emit(Loading) }
    .mapLatest { 
        if (it is Loding) delay(someDelay)
        it
    }
❤️ 2
👍 2
l
Neat.
z
Crazy how simple that is.
You'd have to store some state so only the first emission delays, but very nice
l
You can use the
withIndex()
operator, and return
it.value
in
mapLatest
instead of
it
.