Package-level declarations

Types

Link copied to clipboard
abstract class Bloc<out State : Any, in Action : Any, SideEffect : Any> : BlocState<State, Action>

The core class of the framework. (can't be an interface or the generic types are erased in Swift)

Link copied to clipboard
interface BlocContext : LifecycleOwner

Each Bloc receives a BlocContext.

Link copied to clipboard
abstract class BlocObservable<out State : Any, out SideEffect : Any>

A Bloc than can be observed by subscribing to state and side effect updates (has a subscribe function).

Link copied to clipboard
interface BlocObservableOwner<out State : Any, out SideEffect : Any>

A class is a BlocObservableOwner if it holds and exposes a BlocObservable.

Link copied to clipboard
interface BlocOwner<out State : Any, in Action : Any, SideEffect : Any, Proposal : Any>

A class is a BlocOwner if it holds and exposes a Bloc.

Link copied to clipboard
class ComponentLazy<A : ViewModelStoreOwner, Component : Any>(owner: Lazy<A>, key: Any, create: (context: BlocContext) -> Component) : Lazy<Component>
Link copied to clipboard
interface Sink<in Value : Any>

A Sink is a generic destination for data.

Link copied to clipboard
interface StateStream<out Value : Any>

A StateStream is a source of asynchronous (state) data. It's a hot stream, identical to kotlinx.coroutines.flow.StateFlow without exposing the replayCache and meant to deal with State data (compared to SideEffectStream for SideEffects).

Functions

Link copied to clipboard
fun <T : ViewDataBinding> ComponentActivity.bind(@LayoutRes layoutId: Int, bindLayout2Component: (T) -> Unit)

ComponentActivity / AppCompatActivity / Fragment

Link copied to clipboard
@JvmName(name = "blocProposalEqualsStateInitialValue")
fun <State : Any, Action : Any, SideEffect : Any> bloc(context: BlocContext, initialValue: State, block: BlocBuilder<State, Action, SideEffect, State>.() -> Unit = {}): Bloc<State, Action, SideEffect>
@JvmName(name = "blocNoSideEffectsInitialValue")
fun <State : Any, Action : Any> bloc(context: BlocContext, initialValue: State, block: BlocBuilder<State, Action, Unit, State>.() -> Unit = {}): Bloc<State, Action, Unit>
@JvmName(name = "bloc")
fun <State : Any, Action : Any, SideEffect : Any, Proposal : Any> bloc(context: BlocContext, blocState: BlocState<State, Proposal>, block: BlocBuilder<State, Action, SideEffect, Proposal>.() -> Unit = {}): Bloc<State, Action, SideEffect>
@JvmName(name = "blocProposalEqualsState")
fun <State : Any, Action : Any, SideEffect : Any> bloc(context: BlocContext, blocState: BlocState<State, State>, block: BlocBuilder<State, Action, SideEffect, State>.() -> Unit = {}): Bloc<State, Action, SideEffect>
@JvmName(name = "blocNoSideEffects")
fun <State : Any, Action : Any> bloc(context: BlocContext, blocState: BlocState<State, State>, block: BlocBuilder<State, Action, Unit, State>.() -> Unit = {}): Bloc<State, Action, Unit>

Creates a Bloc instance using a BlocBuilder.

Link copied to clipboard

Create a BlocContext from a ViewModel. The lifecycle will be the "lifecycle" of the ViewModel.

Link copied to clipboard
fun <State : Any, Action : Any, SideEffect : Any> collectSideEffects(bloc: <Error class: unknown class><State, Action, SideEffect>): <Error class: unknown class><<Error class: unknown class>, MutableList<SideEffect>>
Link copied to clipboard
fun <State : Any, Action : Any, SideEffect : Any> collectState(bloc: <Error class: unknown class><State, Action, SideEffect>): <Error class: unknown class><<Error class: unknown class>, MutableList<State>>
Link copied to clipboard
inline fun <A : ViewModelStoreOwner, Component : Any> A.getOrCreate(key: Any = Component::class, noinline create: (context: BlocContext) -> Component): Lazy<Component>

Use this from an Activity or a Fragment to get or create a "Component" without directly involving a ViewModel, e.g.:

Link copied to clipboard

Submit a Reducer without side effects to a BlocOwner/Bloc to be run. The reducer will receive the state but no action (since it was triggered "manually", not by sending an action to the Bloc).

Submit a Reducer without side effects to a Bloc to be run. The reducer will receive the state but no action (since it was triggered "manually", not by sending an action to the Bloc).

Link copied to clipboard

Submit a Reducer with side effects to a BlocOwner/Bloc to be run. The reducer will receive the state but no action (since it was triggered "manually", not by sending an action to the Bloc).

Submit a Reducer with side effects to a Bloc to be run. The reducer will receive the state but no action (since it was triggered "manually", not by sending an action to the Bloc).

Link copied to clipboard
fun runTests(block: suspend () -> Unit): <Error class: unknown class>

runTest() ignores all delay() calls so most tests would fail since they test asynchronous code

Link copied to clipboard

Submit a SideEffect to a BlocOwner/Bloc to be emitted. The side effect will receive the state but no action (since it was triggered "manually", not by sending an action to the Bloc).

Submit a SideEffect to a Bloc to be emitted. The side effect will receive the state but no action (since it was triggered "manually", not by sending an action to the Bloc). Note: the proposal is irrelevant for sideEffect so we set it to Unit

Link copied to clipboard
fun <State : Any, SideEffect : Any> BlocObservableOwner<State, SideEffect>.subscribe(lifecycleOwner: LifecycleOwner, state: suspend (state: State) -> Unit? = null, sideEffect: suspend (sideEffect: SideEffect) -> Unit? = null)

Subscribes to a BlocObservableOwner (typically a ViewModel, a Fragment or an Activity). The subscription is tied to the lifecycle of a LifecycleOwner (normally an Activity or Fragment).

fun <State : Any, Action : Any, SideEffect : Any, Proposal : Any> BlocOwner<State, Action, SideEffect, Proposal>.subscribe(lifecycleOwner: LifecycleOwner, state: suspend (state: State) -> Unit? = null, sideEffect: suspend (sideEffect: SideEffect) -> Unit? = null)

Same as above for a BlocOwner

fun <State : Any, Action : Any, SideEffect : Any> Bloc<State, Action, SideEffect>.subscribe(lifecycleOwner: LifecycleOwner, state: suspend (state: State) -> Unit? = null, sideEffect: suspend (sideEffect: SideEffect) -> Unit? = null)

Same as above for a Bloc

Link copied to clipboard
suspend fun <State : Any, Action : Any, SideEffect : Any> testCollectSideEffects(bloc: <Error class: unknown class><State, Action, SideEffect>, expected: List<SideEffect>, block: suspend () -> Unit)
Link copied to clipboard
suspend fun <State : Any, Action : Any, SideEffect : Any> testCollectState(bloc: <Error class: unknown class><State, Action, SideEffect>, expected: List<State>, block: suspend () -> Unit)
suspend fun <State : Any, Action : Any, SideEffect : Any> testCollectState(bloc: <Error class: unknown class><State, Action, SideEffect>, expected: List<State>, delay: Long = 100, block: suspend () -> Unit)
Link copied to clipboard
suspend fun <State : Any, Action : Any, SideEffect : Any> testState(bloc: <Error class: unknown class><State, Action, SideEffect>, action: Action?, expected: State, delay: Long = 10)
Link copied to clipboard

Submit a Thunk to a BlocOwner/Bloc to be run. The thunk will receive the dispatch and the getState function but no action (since it was triggered "manually", not by sending an action to the Bloc). The dispatch function dispatches to the first matching thunk/reducer/side-effect in the Bloc.

@JvmName(name = "BlocOwnerThunkSimplified")
fun <State : Any, Action : Any, SideEffect : Any> BlocOwner<State, Action, SideEffect, State>.thunk(thunk: ThunkNoAction<State, Action, State>)

Submit a Thunk to a BlocOwner/Bloc to be run. Simplified version with Proposal = State.

Submit a Thunk to a Bloc to be run. The thunk will receive the dispatch and the getState function but no action (since it was triggered "manually", not by sending an action to the Bloc). The dispatch function dispatches to the first matching thunk/reducer/side-effect in the Bloc.

@JvmName(name = "BlocThunkSimplified")
fun <State : Any, Action : Any, SideEffect : Any> Bloc<State, Action, SideEffect>.thunk(thunk: ThunkNoAction<State, Action, State>)

Submit a Thunk to a Bloc to be run. Simplified version with Proposal = State.

Link copied to clipboard

The same for Activities / Fragments

Expose a Bloc as LiveData so it can be used with Android data binding, e.g.:

Link copied to clipboard

If a components implements the BlocObservableOwner interface it needs to provide

The assumption is that all Blocs use the same BlocState with the same type parameters (enforced at compile time) but also that they share the same instance of a BlocState (not enforced at all). Under that assumption we only need to observe the state of the first Bloc to observe all state changes. The edge-case that one passes in multiple Blocs using different BlocStates could be covered by using a UUID for BlocState instances and then verify that all BlocStates have the same UUID but that would be over-engineering imo.

Same as above but combine just two Blocs to BlocObservable.