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()