Mobius Tutorial for Android: Getting Started
Learn about Mobius, a functional reactive framework for managing state evolution and side effects and see how to connect it to your Android UIs. By Massimo Carli.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Mobius Tutorial for Android: Getting Started
30 mins
- Getting Started
- Understanding Mobius Principles and Concepts
- Mobius Update Function
- The Mobius Workflow
- Modeling Your App
- Defining External Events
- Capturing User Interactions
- Defining Effects
- Defining Your Model
- Defining Effects Feedback Events
- Describing Your App
- Memory Game Update Function
- Implementing Back-Out Functionality
- Handling Effects
- Mobius and Android
- Where to Go From Here?
Mobius and Android
Mobius is much more than what you’ve learned in this tutorial. As one last point, it’s interesting to look at how Mobius is connected to Android and Jetpack Compose. Open MainActivity.kt, and look at the following code:
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
@Inject
lateinit var gameCardController: CardGameMobiusController // 1
private var gameModel = mutableStateOf(CardGameModel())
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Switch to AppTheme for displaying the activity
setTheme(R.style.AppTheme)
gameCardController.connect(::connectViews) // 2
setContent {
MainScreen(gameModel.value, eventConsumer)
}
}
override fun onDestroy() {
super.onDestroy()
gameCardController.disconnect() // 5
}
override fun onResume() {
super.onResume()
gameCardController.start() // 5
}
override fun onPause() {
super.onPause()
gameCardController.stop() // 5
}
override fun onBackPressed() {
eventConsumer.accept(BackPressed) // 6
}
lateinit var eventConsumer: Consumer<CardGameEvent>
private fun connectViews(
eventConsumer: Consumer<CardGameEvent>
): Connection<CardGameModel> { // 2
this.eventConsumer = eventConsumer
return object : Connection<CardGameModel> {
override fun accept(model: CardGameModel) {
logic(eventConsumer, model) // 3
}
override fun dispose() {
}
}
}
var logic: (Consumer<CardGameEvent>, CardGameModel) -> Unit =
{ _, cardModel ->
gameModel.value = cardModel // 4
}
}
Here, you:
- Declare a
CardGameMobiusController
, which is a typealias ofMobiusLoop.Controller<CardGameModel, CardGameEvent>
. This is basically the Mobius loop that handles all the concepts you learned in the introduction. This is the one responsible for handling events and triggering effects. - In the
onCreate
, you connect the loop to theconnectViews
function, which returns an implementation ofConnection<CardGameModel>
. This is basically a callback for the lifecycle of the Mobius loop. - Every time an event is sent, the
accept
function is invoked. This is where the magic happens, calling thelogic
function. - The
logic
function updates the model used by Jetpack Compose. - Note how the lifecycles of the
Activity
and the Mobius loop are connected. - The
Consumer<CardGameEvent>
is the object you use to send events. How the back navigation event is handled is a good example of its usage.
You can spend some time seeing how all the dots are connected.
Where to Go From Here?
Congratulations! You learned how Mobius works by implementing a simple game. Use the Download Materials button at the top or bottom of the tutorial to access the final version of the code.
As mentioned, Mobius is much more than this. Besides the official documentation, a possible next step is the chapter about Mobius in Functional Programming in Kotlin by Tutorials.
If you have any questions or comments, please join the discussion below!