Home

Awesome

TODO-MOBIUS

Summary

This sample is based on the TODO-MVP-RXJAVA project from the Android Architecture Blueprints repository. It converts the code from MVP using RxJava to a Mobius implementation.

Compared to the TODO-MVP-RXJAVA, this project implements all business logic and presentation logic as pure functions, and utilizes Mobius to manage state and side-effects. Presenters are called ViewDataMappers and they are pure functions that accept Model instances and return ViewData objects that are then bound to the UI. Furthermore, views were extracted into separate classes used by fragments. Data Source implementations were reused.

The TasksRepository class has been removed as its responsibility is achieved using a Mobius update function.

The project contains four features. Each feature's implementation is a little unique to show the different approaches to modeling in Mobius. Here are the highlights:

Each feature is divided into the following package structure:

Features in this project treat Fragments as builders that are only responsible for managing lifecycle and creating dependencies. Each Fragment creates a MobiusLoop.Controller and connects it to the view, which is now a separate Views class, owned by the Fragment. Once a MobiusLoop.Controller is started, it'll start the MobiusLoop which kicks things off by invoking the Init function. The Init and Update functions define how state should evolve and what effects should happen. The UI is purely derived from the representation of state, i.e. the Model. There are helper methods that turn Models into Bundles and vice versa. These are used for state restore.

Mobius uses a computation thread to process events, i.e. invoke Init/Update functions. This thread is synchronized and events are processed one at a time. It also utilizes an ExecutorService to process effects returned by the logic functions. MobiusLoop.Controller makes sure Model updates are delivered on the main thread for rendering.

There's a helper builder accessible through RxMobius.subtypeEffectHandler() that allows you to specify an effect handler per effect type. Here's the definition of the effect handlers for the AddEditTask feature

ObservableTransformer<AddEditTaskEffect, AddEditTaskEvent> effectHandler =
     RxMobius.<AddEditTaskEffect, AddEditTaskEvent>subtypeEffectHandler()
       .addAction(NotifyEmptyTaskNotAllowed.class, showEmptyTaskError, mainThread()) // where showEmptyTaskError is an Action implementation
       .addAction(Exit.class, showTasksList, mainThread()) // where showTasksList is an Action implementation
       .addFunction(CreateTask.class, createTaskHandler(remoteSource, localSource)) // where createTaskHandler returns an Function<CreateTask, AddEditTaskEvent>
       .addFunction(SaveTask.class, saveTaskHandler(remoteSource, localSource)) //where saveTaskHandler returns an Function<SaveTask, AddEditTaskEvent>
       .build();

For more information about Effect Handlers, please refer to the Mobius Wiki

Dependencies

Features

Complexity - understandability

Use of architectural frameworks/libraries/tools:

Mobius simplifies building of business logic by turning it into a synchronous pure function.

Conceptual complexity

A couple of new concepts that need to be learned such as Pure functions and Sum Types.

Testability

Unit testing

Very High. For the following reasons:

UI testing

UI testing can be split into two categories of tests:

Maintainability

Ease of amending or adding a feature

High.

Learning cost

External contributors

Mobius Implementation:

Original Implementation:

This project adheres to the Open Code of Conduct. By participating, you are expected to honor this code.