BaseReactiveState

open class BaseReactiveState<E : ErrorEvents>(val scope: CoroutineScope) : ReactiveState<E>

Base class/delegate for ViewModels and other objects that can trigger one-time events/actions and handle errors.

Make sure you always launch coroutines via launch (instead of the scope) to get automatic error handling.

Example:

// You can compose multiple events interfaces with simple inheritance (more elegant than sealed classes)
interface FooEvents : ErrorEvents, OtherEvents, AndMoreEvents {
fun onUserIsUnauthorized()
}

class FooViewModel(scope: CoroutineScope) : BaseReactiveState<FooEvents>(scope) {
private val _messages = MutableStateFlow<List<Message>>(emptyList())
val messages: StateFlow<List<Messages>> = _messages

init {
loadMessages()
}

fun loadMessages() {
launch {
// Let's pretend this function returns null for unauthorized requests
val messages = retrieveMessagesFromBackend()
if (messages == null) {
eventNotifier { onUserIsUnauthorized() }
} else {
_messages.value = messages
}
}
}
}

Constructors

Link copied to clipboard
constructor(scope: CoroutineScope)

Properties

Link copied to clipboard
open override val eventNotifier: EventNotifier<E>
Link copied to clipboard
open override val loading: MutableStateFlow<Int>

The default loading tracker.

Link copied to clipboard
override val scope: CoroutineScope

The underlying CoroutineScope of this launcher.

Functions

Link copied to clipboard

Watches observables for changes. Often useful to keep things in sync (e.g. CoroutineLauncher -> UI).

Link copied to clipboard
fun CoroutineLauncher.coAutoRun(onChange: CoAutoRunOnChangeCallback<Unit>? = null, flowTransformer: AutoRunFlowTransformer = { conflatedWorker(transform = it) }, dispatcher: CoroutineDispatcher = dispatchers.main, withLoading: MutableStateFlow<Int>? = loading, observer: CoAutoRunCallback<Unit>): CoAutoRunner<Unit>

Watches observables for changes. Often useful to keep things in sync (e.g. CoroutineLauncher -> UI).

Link copied to clipboard
fun <T> CoroutineLauncher.derived(synchronous: Boolean = true, cache: Boolean = synchronous, observer: AutoRunCallback<T>): StateFlow<T>

Creates a StateFlow that computes its value based on other StateFlows via an autoRun block.

fun <T> CoroutineLauncher.derived(initial: T, started: SharingStarted = SharingStarted.Eagerly, flowTransformer: AutoRunFlowTransformer = { conflatedWorker(transform = it) }, dispatcher: CoroutineDispatcher = dispatchers.main, withLoading: MutableStateFlow<Int>? = loading, observer: CoAutoRunCallback<T>): StateFlow<T>

Creates a StateFlow that computes its value based on other StateFlows via a suspendable coAutoRun block.

Link copied to clipboard
fun CoroutineLauncher.invokeOnCompletion(handler: CompletionHandler): Disposable

Helper for adding a completion handler to a CoroutineLauncher.

Link copied to clipboard
open fun launch(context: CoroutineContext = EmptyCoroutineContext, start: CoroutineStart = CoroutineStart.DEFAULT, withLoading: MutableStateFlow<Int>? = loading, onError: suspend (Throwable) -> Unit? = null, block: suspend CoroutineScope.() -> Unit): Job

Launches a coroutine. Mark long-running coroutines by setting withLoading to loading state.

Link copied to clipboard
open override fun onError(error: Throwable)
Link copied to clipboard
open fun rawLaunch(context: CoroutineContext, start: CoroutineStart, block: suspend CoroutineScope.() -> Unit): Job

Launches a coroutine without any error handling or loading state tracking.

Link copied to clipboard
open suspend fun track(withLoading: MutableStateFlow<Int>? = loading, onError: suspend (Throwable) -> Unit? = null, block: suspend () -> Unit)

Tracks a suspension block's loading state and errors.

Link copied to clipboard