# Mobius makes an Android app's state a pure function of its events

> Mobius is Spotify's functional reactive framework for managing state evolution and side-effects, where all state lives in a model, changes arrive as events, and a single update function maps model plus event to the next model. The core is a self-contained Java library, with optional modules for RxJava, Kotlin Coroutines and Android, and the project is in production status at Spotify.

**spotify/mobius** — A functional reactive framework for managing state evolution and side-effects.

- Repository: https://github.com/spotify/mobius
- Website: https://spotify.github.io/mobius/
- Stars: 1,265 · Forks: 106
- Language: Java
- License: Apache-2.0
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/spotify-mobius

## State is a snapshot, and you never touch it directly

Mobius is a functional reactive framework for managing state evolution and side-effects, with add-ons for connecting to Android UIs, RxJava Observables and Kotlin Coroutines. It emphasizes separation of concerns, testability, and isolating the stateful parts of the code.

The core idea is stated in the counter example. The goal of Mobius is to give you better control over your application state, and you can think of your state as a snapshot of all the current values of the variables in your application. In Mobius, all of the state is encapsulated in a data structure called the Model, which can be represented by whatever type you like. For a counter that is an Integer.

The constraint is the important part. Mobius does not let you manipulate the state directly. In order to change the state, you have to send the framework messages saying what you want to do, and those messages are called Events. For a counter they are an enum.

```java
enum CounterEvent {
  INCREMENT,
  DECREMENT,
}
```

So the application state is never mutated. It is replaced. Every change is a transition from one snapshot to the next, and the transitions are described by data, which is what makes them testable.

## One pure function does the state transition

With a model and some events, the framework needs the rules for updating the state. You give it a function which is called sequentially with every incoming event and the most recent model, in order to generate the next model.

```java
class CounterLogic {
  static Integer update(Integer model, CounterEvent event) {
    switch (event) {
      case INCREMENT: return model + 1;
      case DECREMENT: return model - 1;
    }
  }
}
```

The properties of that function are the whole argument for the framework. It is total, because it returns a new model for every event, it has no side effects, and it depends on nothing but its two arguments. A test for it needs no mocks, no Android runtime and no main thread.

That is why the framework is worth the indirection for a state machine that has grown complex. The complexity does not go into the framework, it goes into the update function, and that function is the one part of the application that is genuinely easy to test.

The readme then makes the point that with these building blocks you can start to think of your applications as transitions between discrete states in response to events, and then it names the piece that is still missing, namely the side-effects which are associated with moving between states. The available text stops there, so the effect handling is the part you will have to read about in the user guide on the project website.

## The module family, and which one you actually need

The library is published as a set of Maven artifacts, and the readme is careful to say which are optional.

mobius-core is the core of Mobius, which all other modules depend on. It is a pure Java library that is completely self-contained, and it is the only module you need when using Mobius, because the others are optional extensions to the core.

mobius-test contains utilities that help you write tests for Mobius applications, and it should only be used as a test dependency.

The reactive integrations come in versions. mobius-rx, mobius-rx2 and mobius-rx3 are extensions for RxJava, and you should use one of them since they simplify creating effect handlers and event sources. The two RxJava modules share the same API, and the only difference is that one is built for RxJava 1.x and the other for RxJava 2.x.

mobius-android primarily contains classes for hooking up a MobiusLoop to Android.

mobius-coroutines contains utilities for connecting Mobius with Kotlin Coroutines, and it provides suspend function based effect handlers, Flow based event sources, and a subtype effect handler builder with configurable execution policies, which can be sequential, concurrent, or cancel previous.

And mobius-extras contains utilities and classes that help reduce boilerplate for some more advanced usage patterns, for example nested update functions.

The dependency snippet makes the shape explicit, with each line commented by what it is for.

```groovy
implementation 'com.spotify.mobius:mobius-core:LATEST_RELEASE'
testImplementation 'com.spotify.mobius:mobius-test:LATEST_RELEASE'
```

That is a good default for a team that is not using RxJava or Coroutines: two dependencies, one for the framework and one for the test helpers.

## Production status, and a Java 7 baseline

The Status section is short and it is the part to read before choosing the library.

Mobius is in Production status, meaning it is used in production in Spotify Android applications, that the APIs are considered stable and the implementation bug-free, and that backwards-compatibility-breaking changes will not be made.

That is a meaningful commitment from a company of Spotify's size, and it is the kind of statement that should make you more cautious rather than less, because a stable API that is never changed is also an API that is not gaining new capabilities.

Then there is the constraint. Mobius is currently built for Java 7, because Java 8 is not fully supported on all versions of Android, hence the duplication of some concepts defined in java.util.function, which the readme points at with the package name com.spotify.mobius.functions.

So the library carries its own copies of the functional interfaces that Java 8 put in the standard library, and on a Java 7 target they are the ones you use. On a modern build, that duplication is a historical artefact you can ignore.

And the recommendation that follows is about your code rather than about the library. When using Mobius, the readme recommends Kotlin or Java 8 or later, primarily because of the improved type inference and because using lambdas greatly improves the readability and conciseness of the code.

## Learning it: a sample app and a conference talk

The readme points at three things for learning the framework, and they cover the three ways people actually learn.

The first is the website, which has a user guide.

The second is the sample TODO app, and it is a real application rather than a toy. It is based on the app from the Android Architecture Blueprints, which means the code you read is the code Google published as a reference architecture with the state handling replaced.

The third is a talk, from Android at Scale, introducing Mobius.

What makes the sample app useful is the substitution. The Android Architecture Blueprints app is a well known piece of reference code, so a developer who already knows it can see exactly what Mobius changes, and a developer learning Mobius can see the framework applied to something they recognise as a normal Android app.

The repository also carries the documentation source. There is a docs/ directory with a mkdocs.yml and an mkdocs.sh script, so the user guide is built from the repository, and the site is published on GitHub Pages at spotify.github.io/mobius.

The other artifacts in the tree are the ones a project of this size accumulates: a RELEASING.md for the release process, an apache2.header for the licence headers, a catalog-info.yaml for the build catalogue, a .java-version file, a NOTICE file and a gradle.properties, alongside the build.gradle and settings.gradle.

## The repository is one Gradle module per artifact

The top level listing is a Gradle multi-project build with one directory per published module, and that is the clearest evidence that the modules are independently versioned artifacts rather than packages inside one jar.

There is mobius-core/, mobius-test/, mobius-rx/, mobius-rx2/, mobius-rx3/, mobius-android/, mobius-coroutines/ and mobius-extras/, eight directories for eight artifacts, plus the root build.gradle and settings.gradle, the gradlew and gradlew.bat launchers, the gradle/ directory and the gradle.properties.

The core module being self-contained means the dependency graph of a Mobius application is small. A project that uses the coroutines module pulls in mobius-core and mobius-coroutines, and nothing else from the family, because the modules do not depend on each other beyond the core.

The rest of the tree is the infrastructure. The docs/ directory holds the user guide sources, and there is a NOTICE file and a LICENSE file at the top, plus the apache2.header that the build uses to stamp the licence into the source files, which is the usual way a project keeps licence headers consistent across many modules.

The build badges tell you the rest. There is a Maven Central badge for the core artifact, a codecov coverage badge for the master branch, a licence badge, and a Gitter chat link, and the CI badge at the top is the Travis one, which dates the continuous integration setup to before the GitHub Actions era.

## Conclusion

Adopt Mobius when you are building an Android application whose state logic has grown tangled and you want that logic to be testable without an emulator, since the update function is a plain function of model and event. Do not adopt it for a small app, because the ceremony of a loop is only worth it when the state transitions are genuinely complex. Verify first which optional module you need for your reactive library, since the RxJava modules are version specific, and that you are comfortable with the Java 7 baseline the core is built for, which is what the duplicated function types in com.spotify.mobius.functions are there for.

## FAQ

### What is Mobius?

It is a functional reactive framework for managing state evolution and side-effects, with add-ons for connecting to Android UIs, RxJava Observables and Kotlin Coroutines. It emphasises separation of concerns, testability and isolating the stateful parts of the code.

### How does the Mobius state model work?

All state is encapsulated in a data structure called the Model, and you never mutate it directly. You send Events to the framework, and a single update function is called sequentially with every incoming event and the most recent model to generate the next model, which makes the state logic a pure function you can test without an emulator.

### Which Mobius modules do I need?

Only mobius-core, which is a pure Java library that is completely self-contained. The rest are optional: mobius-test for writing tests, the mobius-rx, mobius-rx2 and mobius-rx3 modules for RxJava 1, 2 and 3, mobius-android for hooking a loop up to Android, mobius-coroutines for Kotlin Coroutines, and mobius-extras for advanced patterns such as nested update functions.

### Is Mobius maintained and stable?

The project states that Mobius is in Production status, used in production in Spotify Android applications, that the APIs are considered stable and the implementation bug-free, and that backwards-compatibility-breaking changes will not be made. The last push was on 2026-08-07 and the latest release is 2.1.1 from 2024-12-12.

### Which Java version does Mobius need?

It is currently built for Java 7, because Java 8 is not fully supported on all versions of Android, which is why some java.util.function concepts are duplicated in com.spotify.mobius.functions. The readme recommends using Kotlin or Java 8 or later in your own code for type inference and lambdas.

### Where can I see Mobius in use?

There is a sample TODO app in a separate repository, based on the app from the Android Architecture Blueprints, and a talk from Android at Scale introducing Mobius, linked from the readme along with the user guide on the project website.

## Sources

- [License: Apache-2.0](https://github.com/spotify/mobius/blob/master/LICENSE)
- [Project website](https://spotify.github.io/mobius/)
- [README](https://github.com/spotify/mobius/blob/master/README.md)
- [Releases](https://github.com/spotify/mobius/releases)
- [spotify/mobius on GitHub](https://github.com/spotify/mobius)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/spotify-mobius
