Appyx Interactions – TransitionModel¶
Overview¶
A TransitionModel
defines the abstract model of the AppyxComponent.
<ModelState>¶
TransitionModel
holds an instance of <ModelState>
, a type defined by the implementation class.
You can find various examples in the repository. Some possible points of interest:
TestDriveModel.State
BackStackModel.State
SpotlightModel.State
CardsModel.State
Model state should have no knowledge of UI-related properties – all of that belongs to the UI layer. You should strive to describe your model in a semantic way that assumes nothing of its visual representation.
For example, TestDriveModel.State
describes an element that can be in 4 possible configurations (the example in this documentation's main page).
Notice how the states, even though simplistic, aren't named TOPLEFT
, TOPRIGHT
, BOTTOMRIGHT
, BOTTOMLEFT
, as the positioning is only done in the UI. This allows to represent them in various different ways, without any assumptions baked in the model.
@Parcelize
data class State<InteractionTarget>(
val element: Element<InteractionTarget>,
val elementState: ElementState
) : Parcelable {
enum class ElementState {
A, B, C, D;
fun next(): ElementState =
when (this) {
A -> B
B -> C
C -> D
D -> A
}
}
}
Another example from BackStackModel.State
, with purely semantic naming:
@Parcelize
data class State<InteractionTarget>(
/**
* Elements that have been created, but not yet moved to an active state
*/
val created: Elements<InteractionTarget> = listOf(),
/**
* The currently active element.
* There should be only one such element in the stack.
*/
val active: Element<InteractionTarget>,
/**
* Elements stashed in the back stack (history).
*/
val stashed: Elements<InteractionTarget> = listOf(),
/**
* Elements that will be destroyed after reaching this state.
*/
val destroyed: Elements<InteractionTarget> = listOf(),
) : Parcelable
<InteractionTarget>¶
This generic type is simply meant for you to identify different child elements in your client code. For example, if you have a tabbed component, and each tab would be identified by a different instance of an enum
or a sealed class
, then this enum
or sealed class
would be your <InteractionTarget>
.
Then, depending on your <ModelState>
and operation implementations, you can affect these targets differently.
Changing the state¶
A TransitionModel
behaves like a state machine. If you want a new ModelState
to be created, you must pass it an instance of an Operation
. You can read more about them in Operations.
Output¶
TransitionModel
has an output flow:
val output: StateFlow<Output<ModelState>>
In most cases don't need to deal with this output directly. The AppyxComponent takes care of that, and channels this flow to the Visualisation
to translate it to a UI representation.