molikto
04/01/2020, 3:03 AMZach Klippenstein (he/him) [MOD]
04/01/2020, 1:36 PMonActive
instead of remember
, so you don’t need to store your subscription in your state.
2. Annotate your state with @Model
, which will automatically wire up recomposition so you don’t need Recompose
or current.composing
.
You probably also want to key the subscription on the observable itself, so if the caller starts passing in a different observable, you update the subscription.
@Model private class State(
var set: Boolean = false,
var value: Any? = null
)
@Composable fun <T> Observe(
@Pivotal observable: Observable<T>,
children: @Composable() (T) -> Unit
) {
val current by remember { State() }
onActive {
val subscription = observable.subscribe {
current.set = true
current.value = it
}
onDispose { subscription.dispose() }
}
@Suppress("UNCHECKED_CAST")
if (current.set) {
children(current.value as T)
}
}
@Pivotal
ensures that, if the caller starts passing in a different observable, your entire Observe
composable is removed from the composition and recreated (including current
and the subscription), which means that children
will temporarily stop getting called until the first value is received from the new observable. If you want to hang onto the last value until the new observable emits, remove the @Pivotal
annotation and change onActive
to onCommit(observable)
, which will keep your state around but just tear down and recreate the subscription.molikto
04/01/2020, 4:10 PMsource.map{}
or source.distinctUntilChanged()
so they don't have a meaningful equals
? I do encountered a lot of time the Observable body needs to be forcely recomposed entirely, these cases I have a key(..)
outside where I manually select a proper keyonActive
will cause the observable body always miss the first frame. If the observable is a ReplaySubject
or a BehaviourSubject
currently having a value, then my code will compose the children during the first frameLeland Richardson [G]
04/03/2020, 3:08 PMZach Klippenstein (he/him) [MOD]
04/03/2020, 5:56 PMmolikto
04/24/2020, 6:04 AMState<T>
is returned. Although in case of Observable you need to provide a default value. I found this works better than what I have before, 1. less indentation... 2. I actually needs to provide an meaningful default value most of time. 2. it is convenient to work with multiple observables compared to combineLatest