RxFlux Android Architecture

Marcel Pintó
The Startup
Published in
7 min readOct 20, 2015

--

This is the first article about the new RxFlux framework. Is small light-weight framework that makes it easy to follow the Flux pattern with RxJava functionalities.

I will not get into the details on how Flux works, in order to understand more how to use Flux pattern in Android, @lgvalle created a nice example and explanation. I would recommend to read it before.

In this article I will explain how to create an app from scratch using RxFlux. If you want to see more specific details in how to use RxFlux, go to the repo. One last note is that I used Retrolambda because everything looks much clear with it.

Please take the sample app in the repo as a reference.

The idea

In any normal app development the first step is to think what do you want to do. The Flux pattern makes it simple to define a structure and specify the desired functionalities.

Let’s imagine that we want to create a simple app that uses the Github API. This app shows a list of repositories to the user and the user can view the owner pressing into the repository item.

Let’s keep this diagram in mind (author @lgvalle)

Logic and functionality

First thing we must think is which “Stores” do we need. In our case, I can think on:

  • RepositoriesStore: will contain the list of GitHubRepos.
  • UsersStore: will contain the list of users we request for each repo.

According to the diagram below, now we need to think what interface shall we define in order that the view gets the needed information. We need to create an interface for each store.

We need to offer an interface for each store

For our Repo store is pretty straightforward, the view just need the list.

public interface RepositoriesStoreInterface {

List<GitHubRepo> getRepositories();

}

In order to show the GitHubUser once clicked an item in the list, we need to get a specific user by id, also we could be interested on getting the full list of users.

public interface UsersStoreInterface {

GitUser getUser(String id);

List<GitUser> getUsers();

}

Once we have defined the model, the next step is to think which are the possible actions that can be triggered by the app behaviour or from user interaction with the app.

A RxAction is divided by Type and Data (key-value pair).

The first thing the app needs is to request the list of repos and then in case the user press one of the items, we need to request the user info for that repo.

public interface Actions {

String GET_PUBLIC_REPOS = "get_public_repos";
String GET_USER = "get_user";

void getPublicRepositories();

void getUserDetails(String userId);
}

We create an interface that will contain all the possible types of actions defined by a key and a method/s that our RxActionCreator will implement.

Last part is to define the Keys that we will use in the key-value pair map inside the RxAction. This Keys will help us retrieve the data when we get a RxAction.

public interface Keys {
String PUBLIC_REPOS = "repos";
String USER = "user";
String ID = "id";
}

In this point the main functionality, type of actions and the model is clearly defined. As you can see adding or removing logic is as simple as defining new Actions or removing them.

Coding

This is the point that we could divide the workload with other developers (if it would be the case) without interfering between each other. Each part is independent. Every part (Store, View, Action…) has been defined and specified what has to return and what it needs, thus we can implement the logic of each part separately.

Let’s start with the Stores. We create our RepositoriesStore that extends RxStore and implements our interface.

public class RepositoriesStore extends RxStore implements RepositoriesStoreInterface {

public static final String ID = "RepositoriesStore";
private ArrayList<GitHubRepo> gitHubRepos;

@Override
public void onRxAction(RxAction action) {
switch (action.getType()) {
case Actions.GET_PUBLIC_REPOS:
this.gitHubRepos = (ArrayList<GitHubRepo>) action.getData().get(Keys.PUBLIC_REPOS);
break;
default: // IMPORTANT if we don't modify the store just ignore
return;
}
postChange(new RxStoreChange(ID, action));
}

@Override
public ArrayList<GitHubRepo> getRepositories() {
return gitHubRepos == null ? new ArrayList<GitHubRepo>() : gitHubRepos;
}
}

RxStore is an abstract class that offers some methods in order to post events and handle the registration into the dispatcher. The constructor needs as a parameter the dispatcher in order to let RxFlux register the store.

The important method here is the onRxAction. This method will be called every time the dispatcher post a RxAction into the bus. Each store will decide what to do with this action (use it or ignore it).

In our case we wait for actions of the type GET_PUBLIC_REPOS. When we get this action we know by the contract of RxFlux that will contain a key called PUBLIC_REPOS with our list of repos. For our simple app we just store it in our variable and post a store change into the dispatcher. This store change needs an ID and a RxAction. The dispatcher will post this change into the bus, the View will receive it and react requesting the data using the getRepositories method.

Now let’s create the action that will give us this list. Looking again to the Flux diagram we need our ActionCreator. RxFlux supplies an abstract class called RxActionCreator which will help us implementing actions. The normal constructor will need the dispatcher and the SubscriptionManager as parameters. We can also supplies it with more parameters if we want.

public class GitHubActionCreator extends RxActionCreator implements Actions {

public GitHubActionCreator(Dispatcher dispatcher, SubscriptionManager manager) {
super(dispatcher, manager);
}

@Override
public void getPublicRepositories() {
final RxAction action = newRxAction(GET_PUBLIC_REPOS);
if (hasRxAction(action)) return;

addRxAction(action, NetworkManager.getApi()
.getRepositories()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(repos -> postRxAction(newRxAction(GET_PUBLIC_REPOS, PUBLIC_REPOS, repos)),
throwable -> postError(action, throwable)));
}
}

GitHubActionCreator will implement our Actions interface defined before. In this method is where we will make all the “async” work (network request, parsing, etc…). First we need to create the action, our action is simple, no parameters, we just call newRxAction(GET_PUBLIC_REPOS) it will give us a new RxAction of the type GET_PUBLIC_REPOS. Next step is to check if we are already doing this action, hasRxAction() will tell us if the action exists and is running.

Now let’s create the request using Retrofit and RxJava. Nothing fancy here, we request the repositories we subscribe to the observable that Retrofit gave, and then we need to implement the onNext method and onError method of the subscription.

When the onNext method returns the new list of repos, we will post a new RxAction with the GET_PUBLIC_REPOS type containing as value the list of repos into the dispatcher. In case we get an error we will use the postError method to let the stores and the views know.

The final step is to create the View and connect the dots. In order to keep this article short I will skip the view creation and only focus on the RxViewDispatch. This interface must be implemented by every activity of the app.

public interface RxViewDispatch {

void onRxStoreChanged(RxStoreChange change);

void onRxError(RxError error);

void onRxViewRegistered();

void onRxViewUnRegistered();

void onRxStoresRegister();
}

The methods are explained in the java docs, but they are pretty clear.

  1. Listen to Store changes, we identify them by store id and action type.
  2. Handle errors.
  3. Get notified when the view has been registered or unregistered from the dispatcher, so we can register other view like fragments.
  4. onRxStoresRegister is an important method, is where the instance of the store must be registered. Best approach is to use DI like dagger, get the instance of the store and call the register method. (Note: the dispatcher is clever enough to ignore if the store was registered, so you can safely register several times)
@Override
public void onRxStoresRegister() {
repositoriesStore.register();
usersStore.register();
}

After this method, both stores will be registered in the dispatcher. If you check the source code you will see that this method is called during the onCreate of the activity. RxFlux will handle the unregister.

Connect the last dot

Finally we just need one last thing, in our Application instance. We must init the RxFlux class. This class will handle the creation of the dispatcher, SubscriptionManager and the RxBus, also will handle the life cycle of the app in order to register and unregister views and stores to avoid memory leaks.

@Override
public void onCreate() {
super.onCreate();
rxFlux = RxFlux.init(this);
}

Final notes

I skipped a few methods and it probably seems complex but as soon as you practice a bit, I hope you will realize that is a great design pattern and together with RxJava give the developer and amazing tool to create an app, also the well defined and clear structure makes it really easy to expand and add extra functionality, easy to test and add new modules. For example for tracking, can be done by creating a new module that register into the dispatcher and listen all the RxActions and track the results.

The framework is in an early stage, if you decide to start using it or have some suggestion to improve it, I am open to PR or new ideas.

Please if you like it share it, also I will be happy to answer any related question.

Happy coding!

Find me on: Twitter: @marxallski and Google+

Previouse stories: Reactive Android Form

--

--

Marcel Pintó
The Startup

Android and Flutter expert, founder of https://pibi.studio a mobile experts hub for building apps and providing expertise. Other projects: https://namewith.ai