State Machine
A state machine library for Kotlin, with extensions for Android.
States and Events
A state machine takes three generic parameters: the events it takes in, the states it spits out,
and the arguments it finishes with. These could be sealed classes, or plain classes & objects.
Building a Machine
A basic machine only requires the core module without any extensions.
Gradle Dependency
Basics
Your state machine should be a subclass of the StateMachine
class.
When the react
method is called, your machine should setup handlers for states. Each state
handles a set of events, each event returns a state. The state should propagate to the UI, and the
UI should send in events when there is interaction. It's a loop, which is basically what a state
machine is.
Usage
This example below demonstrates usage from a JVM command-line program.
Using a Machine on Android
On Android, there are extension modules that you can use to make connecting your states and UI much
easier. Annotation processing is used to generate view models from your state.
Gradle Dependency
On Android, your application should depend on the core-android
module as an implementation
dependency, and the core-android-processor
module as an annotation processor (with kapt
).
States and View Models
Your state must be tagged with the @StateToViewModel
annotation. Only the parent class should be tagged.
This will generate a ViewModel
that you can use in your UI. From the above state,
you'd get something similar to this (some details are omitted because they aren't relevant):
Dispatchers
On Android, being thread conscious is important. StateMachine
's constructor takes two coroutine
dispatchers - one for background execution, and one for the main thread.
Usage
In your Activity, Fragment, etc. you can use the generated ViewModel
s like you would without
this library.
Your UI will automatically receive propagated values from your states as they come in. The
generated view model will automatically distinct values as well, so you won't receive duplicate
emissions (which could result in unnecessary UI invalidation).
If you're familiar with LiveData
, you'll also know that this implementation is
totally lifecycle safe. LiveData
will not emit if the lifecycle owner is no longer
started.
Unit Testing Machines
A core-test
module is provided to aid in unit testing your state machines.
Gradle Dependency
Usage
Here's a simple example of a JUnit test, for the state machine above.