BlocObservable
A BlocObservable is an object with a subscribe() function to observe state changes and side effects:
public fun subscribe(
lifecycle: Lifecycle,
state: (suspend (state: State) -> Unit)? = null,
sideEffect: (suspend (sideEffect: SideEffect) -> Unit)? = null
)
The subscription is tied to the (Essenty) lifecycle of the caller (see Lifecycle) meaning with an onStop() event, the subscription ends as well.
A BlocObservable also exposes the bloc's current state as the subscribe()'s state function will only be called when the bloc's state changes:
public val value: State
You will likely never call this directly but use one of the extension functions.
BlocObservableOwner
Sometimes a component should not expose the Bloc as it would when implementing the BlocOwner interface. If a component only requires users to observe the bloc's state and side effects (no actions or actions are encapsulated by the component), BlocObservableOwner is the right choice.
While a BlocOwner exposes a Bloc as property, BlocObservableOwner exposes a BlocObservable as property:
public interface BlocObservableOwner<out State : Any, out SideEffect : Any> {
public val observable: BlocObservable<State, SideEffect>
}
While BlocOwner gives the implementing class the ability to use the "MVVM+" syntax, BlocObservableOwner gives users of an implementing class the ability to observe state and side effects with a single subscribe call:
// the ViewModel implements BlocObservableOwner
viewModel.subscribe(this, state = ::observeState, sideEffect = ::observeSideEffects)
private fun observeState(state: State) {
// process the new state
when (state) {
Empty -> showEmptyPage()
Loading -> showLoadingPage()
is Loaded -> showContent(state)
is Failure -> showError(state)
}
}
private fun observeSideEffects(target: Target) {
// process side effects
navigateTo(target)
}
As you can see in the subscribe function's signature, state and sideEffect are optional arguments so you can subscribe to both or just one of the them.
Adapter
To simplify the implementation of a BlocObservableOwner, use toObservable() to "convert" a Bloc:
// we can keep the Bloc private!
private val bloc = bloc(blocContext(context))
// and only expose the BlocObservable
override val observable = bloc.toObservable()