Code Monkey home page Code Monkey logo

android-flux-todo-app's Introduction

Flux Architecture on Android

Finding a good architecture for Android applications is not easy. Google seems to not care much about it, so there is no official recommendation on patterns beyond Activities lifecycle management.

But defining an architecture for your application is important. Like it or not, every application is going to have an architecture. So you'd better be the one defining it than let it just emerge.

Today: Clean Architecture

Current trend is to adapt Clean Architecture, a 2012 Uncle Bob proposal for web applications.

Although, Clean Architecture could be a little bit over-engineered for most of the Android apps out there.

Typically mobile apps live shorter than web apps. Mobile technology is evolving so fast that any app released today is going to be completely deprecated in twelve months.

Mobile apps usually do very little. A very high percent of use cases are just for data consuming. Get data from API, show data to user. Lot of reads, very little writes.

As a result its business logic is not complex. At least not as complex as backend apps. Well you have to deal with platform issues: memory, storage, pause, resume, network, location, etc. But that is not your app business logic. You have all of that in every app.

So it seems that most of the apps out there will not benefit from things like complex layer divisions or job priority execution queues.

They may just need a simple way to organise code, work together efficiently and find bugs easily.

Introducing Flux Architecture

Flux Architecture is used by Facebook to build their client- side web applications. Like Clean Architecture it is not intended for mobile apps, but its features and simplicity will allow us to adapt it very well to Android projects.

flux-graph-simple

There are two key features to understand Flux:

  • The data flow is always unidirectional.

    An unidirectional data flow is the core of the Flux architecture and is what makes it so easy to learn. It also provides great advantages when testing the application as discussed below.

  • The application is divided into three main parts:

    • View: Application interface. It create actions in response to user interactions.
    • Dispatcher: Central hub through which pass all actions and whose responsibility is to make them arrive to every Store.
    • Store: Maintain the state for a particular application domain. They respond to actions according to current state, execute business logic and emit a change event when they are done. This event is used by the view to update its interface.

This three parts communicate through Actions: Simple plain objects, identified by a type, containing the data related to that action.

Flux Android Architecture

The main target of using Flux principles on Android development is to build an architecture with a good balance between simplicity and ease of scale and test.

First step is to map Flux elements with Android app components.

Two of this elements are very easy to figure out and implement.

  • View: Activity or Fragment
  • Dispatcher: An event bus. I will use Otto in my examples but any other implementation should be fine.

Actions

Actions are not complex either. They will be implemented as simple POJOs with two main attributes:

  • Type: a String identifying the type of event.
  • Data: a Map with the payload for this action.

For example, a typical action to show some User details will look like this:

Bundle data = new Bundle();
data.put("USER_ID", id);
Action action = new ViewAction("SHOW_USER", data);

Stores

This is perhaps the most difficult to get Flux concept.

Also if you have worked with Clean Architecture before it also will be uncomfortable to accept, because Stores will assume responsibilities that were previously separated into different layers.

Stores contain the status of the application and its business logic. They are similar to rich data models but they can manage the status of various objects, not just one.

Stores react to Actions emitted by the Dispatcher, execute business logic and emit a change event as result.

Stores only output is this single event: change. Any other component interested in a Store internal status must listen to this event and use it to get the data it needs.

No other component of the system should need to know anything about the status of the application.

Finally, stores must expose an interface to obtain application Status. This way, view elements can query the Stores and update application UI in response.

flux-graph-store

For example, in a Pub Discovery App a SearchStore will be used to keep track of searched item, search results and the history of past searches. In the same application a ReviewedStore will contain a list of reviewed pubs and the necessary logic to, for example, sort by review.

However there is one important concept to keep in mind: Stores are not Repositories. Their responsibility is not to get data from an external source (API or DB) but only keep track of data provided by actions.

So how Flux application obtain data?

Network requests and asynchronous calls

In the initial Flux graph I intentionally skipped one part: network calls. Next graph completes first one adding more details:

flux-graph-complete

Asynchronous network calls are triggered from an Actions Creator. A Network Adapter makes the asynchronous call to the corresponding API and returns the result to the Actions Creator.

Finally the Actions Creator dispatch the corresponding typed Action with returned data.

Having all the network and asynchronous work out of the Stores has has two main advantages:

  • Your Stores are completely synchronous: This makes the logic inside a Store very easy to follow. Bugs will be much easier to trace. And since all state changes will be synchronous testing a Store becomes an easy job: launch actions and assert expected final state.

  • All actions are triggered from an Action Creator: Having a single point at which you create and launch all user actions greatly simplifies finding errors. Forget about digging into classes to find out where an action is originated. Everything starts here. And because asynchronous calls occur before, everything that comes out of ActionCreator is synchronous. This is a huge win that significantly improves traceability and testability of the code.

Show me the code: To-Do App

In this example you will find a classical To-Do App implemented on Android using a Flux Architecture.

I tried to keep the project as simple as possible just to show how this architecture can produce very well organised apps.

Some comments about implementation:

  • The Dispatcher is implemented using Otto Bus. Any bus implementation will mostly work. There is a Flux restriction on events I’m not applying here. On original Flux definition dispatching an event before previous one has finish is forbidden and will throw an exception. To keep the project simple I’m not implementing that here.

  • There is an ActionsCreator class to help creating Actions and posting them into the Dispatcher. It is a pretty common pattern in Flux which keeps things organised.

  • Actions types are just String constants. It is probably not the best implementation but is quick and helps keeping things simple.

Same thing with Actions data: they are just a HashMap with a String key and Object as a value. This forces ugly castings on Stores to extract actual data. Of course, this is not type safe but again, keeps the example easy to understand.

Conclusion

There is no such thing as the Best Architecture for an Android app. There is the Best Architecture for your current app. And it is the one that let you collaborate with your teammates easily, finish the project on time, with quality and as less bugs as possible.

I believe Flux is very good for all of that.

Sample source code

https://github.com/lgvalle/android-flux-todo-app

Further Reading:

Thanks

Special thanks to my colleague Michele Bertoli for taking the time to introduce me to Flux and for reviewing this post.

android-flux-todo-app's People

Contributors

lgvalle avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

android-flux-todo-app's Issues

ActionCreator is too fat ?

Architecture

In this architecture, ActionCreator file contains:

  • methods when User interact with UI. However there are many activities, and many interaction.
  • methods interact with API adapter.

I think there are many methods in ActionCreator file.

  • Do you think this file is too fat ?
  • And do you have solution for this issue ?

How to handle popup dialog?

Hi,
I am new start of Flux.
Step :

  1. Started a new activity.
  2. Display a popup box for the message from previous activity
    e.g. Type username press login, go to Home page display the popup.

Questions:

  1. Is trigger the popup from Activity directly?
    OR
    Activity (passing message & activity [Home Activity]) => ActionCreator => Dispatcher => Store (invoke activity function to display popup with the message passing in from first step) => Activity (same activity [Home Activity])?

  2. Should keep the message in Store instead of intent?

about dispatcher and store

As shown, all calls are one-way, but in your code is : View -> Actions Creator -> Action -> Dispatcher -> Store -> Dispatcher -> View. which calls the dispatcher in TodoStore not feeling well.

Issue with Single Dispatcher

#Hi lgvalle,

Thankyou for the code implementation, that help me understand flux architecture really well.

I have implemented your architecture in my code. But at one point came I had to break the rule of single dispatcher which is the core of flux architecture.

While there are some actions that are being propagate through UI, I have a background service that hits api server every 30 seconds. As soon as one store working on UI event, another store change event from background service register by dispatcher that nullifies my last change event call and post a null object to OTTO event bus hence view controller in UI never informed that the task is finished. To resolve this problem I had to create another dispatcher to keep background service work on separate thread thus ended up in breaking the rule of single dispatcher.

Please help me to resolve my issue.
Omama Moin

Replace Bus with RxJava

... since you're already using RxJava. Square also recommends switching to it.

Deprecated!
This project is deprecated in favor of RxJava and RxAndroid. These projects permit the same event-driven programming model as Otto, but they’re more capable and offer better control of threading.

Where do you want to put DB ?

In your architecture, I don't know where is right place of DB layer (ORM, datasource, sqlite, ...)
Could you explain (or draw architecture) detail of DB layer ?

List is blank after rotate

Steps to reproduce:

  1. enter some items
  2. rotate

Result:
you see empty list and the input view with opened keyboard. Even if you close the keyboard, the list still empty.

The list is refreshed again once you enter new item.

Breaking unidirectional data flow principle ??

Thanks for this very good example it helped me a lot to get started with the flux architecture. And I am implementing it in my application.

I am wondering, if by having a reference to the Dispatcher in the Store and emitting the Store changes event with this Dispatcher you are not breaking the unidirectional principal ?

I think that by using the dispatcher to emit the the event the event goes back from store to the dispatcher. It is where I think there is a problem in your implementation.

If the store was able to emit changes directly to the view then I think the flow will be respected.

Let me know what you think about it

Kevin,

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.