Skip to main content

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

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
tip

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)
}
tip

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