Structure

Clean Architecture

First things first, the project is following a Clean Architecture approach in order to ensure a good code abstraction, by separating the different layers of the app:

Presentation : mainly UI related code (activities, fragments, presenters, …)

: mainly UI related code (activities, fragments, presenters, …) Domain : business logic (models, use cases)

: business logic (models, use cases) Data: API related (entities, data sources, repositories)

Patterns

For this project, I chose to mix two different patterns — MVP (Model-View-Presenter) for most of the app and MVVM (Model-View-ViewModel) when in my opinion it makes the more sense (coupled with RecyclerViews using Android Data Binding).

Data Binding is awesome, but you have to know when to use it and where it’s unnecessary. For instance, while it makes sense with RecyclerViews, I’d rather use a view injection tool such as ButterKnife for the traditional Activities and Fragments.

Features

Authentication using e-mail and password

Creating new tasks with priorities and tags

Swipe to mark a task as done

Writing Data

addOnCompleteListener, addOnSuccessListener and addOnFailureListener. They all take a listener as a parameter. But they also have a variant — you can specify a reference to a particular activity so the callbacks are scoped to a given activity only and will not be triggered if the activity went through Activity#onStop().

Make sure you are providing a specific activity as it’s really important to avoid memory leaks.

Retrieving Data

Fetching data with Firebase is where “realtime database” takes on its full meaning.

In simple words, you can add event listeners on each node and be instantly notified in-app of the changes (data updated/added/removed).

Let’s take an example directly from Firebucket.

The user is on the main view (the bucket list) and we want him to know if a task has been added, updated or removed. All we have to do is to add a listener on the node below:

/users-tasks/{user_uuid}/tasks

NB: the code has been modified to be easily readable.

Be mindful with the event listeners:

The closer the target node is to the root node, to more data and events you’ll receive. Do not forget to remove the listeners when you no longer need them.

Rx*

RxJava & RxAndroid

When it comes down to handling events and asynchronous tasks, you won’t find a combination that’s more complete than the combo RxAndroid-RxJava.

Therefore, they could be the subject of an entire article. I recommend this series from Dan Lew if you want to know more about how it works as well as the best practices.

My point is that RxJava is incredibly useful and is starting to get lots of attention from Android developers, including myself.

That’s why I decided to wrap the Firebase events using RxJava Observable/Single (depending on the scenario):

Above is an example using a DisposableObserver. It works the same way as an Observer, except that it implements the Disposable interface and thus can be cancelled at any time (asynchronously).

Memory Leaks

Using tools such as RxJava, Otto, EventBus requires you to be cautious with memory leaks.

For instance with RxJava, in most cases, you have to make sure your Observers are no longer able to receive any data once your user leaves the view.

To do so, you have several options:

Disposing them manually Using CompositeDisposable Using RxLifecycle

CompositeDisposable

I chose to use CompositeDisposable as below:

As you can see below, we create BaseUseCase from which all the use cases will inherit from:

Complete code here.

2. We then make sure the Observer is disposed on LoginPresenter#detachView() .

Complete code here.

That way, you don’t have to worry about anything.

Model Storage

POJO

Plain Java Old Object is the meaning behind this strange acronym. What does it mean?

It means you’ll be able to store your models by using simple Java classes.

JSON

In order to store your objects, Firebase needs to serialise them first, and of course unserialise them when you retrieve your data.

What’s better than the JSON format to do so? As Firebase is using GSON tools to serialise/unserialise, there are few rules that you need to be aware of :

Every stored class must contain an explicit empty constructor. Every stored variable in these classes must have a public getter. Use @Exclude to annotate the methods and fields that you don’t want to serialise. Use @Keep for your entities to avoid Proguard to mess with them.

Task Reminder

With API 21 (Lollipop), Google introduced JobScheduler. Long story short, it is an optimised and smarter version of the AlarmManager.

The flip side is that it is only available for API 21+.

Luckily the Firebase team is providing an alternative based on JobScheduler but backward compatible with API 9 and above called Firebase JobDispatcher.

Therefore, I decided to use this module to set a task reminder:

Compete code here.

Parallel Task Execution

Sometimes you just want to do many things at once.

Let’s take the example of user Sign-In:

We have information about them on both Auth API (credentials) and in the database (user profile information).

Scenario 1 (Serial Tasks)

Scenario 2 (Parallel Tasks)

If one of these tasks fail, finalTask will fail, therefore, it is fair to say that you can consider this task as a transaction.

Parallelisation as above can be tricky to perform correctly on Java/Android. It doesn’t get much easier than what Firebase has to offer in that regard.

It is very similar to Observable#combineLatest() (from RxJava) when you have to execute multiple REST calls asynchronously.

Conclusion

I really enjoyed working on Firebase, everything is easy and works seamlessly. However, I have some noteworthy concerns about it.

Push Notifications

The first one is the lack of module allowing to send push notifications without any HTTP/XMPP server. However, I have no doubts that they will work on that sooner or later.

Google Play Services

The fact that Firebase is dependent on Google Play Services is no small problem — what about non-Google devices, e.g. Amazon devices? Therefore, you’re automatically losing part of the Android market.

Backend Needs

Going for a client-centric option such as Firebase can be a problem if you need third party service access from your backend.

Think Twice

If you start a small to medium project from scratch, Firebase is a really interesting choice with a lot of possibilities and a relatively small amount of time needed to crack on.

On the other hand, for an existing project, It may be a big hassle to migrate.

UPDATE

At the time of writing, Firebase didn’t have the Cloud Functions. It is a game changer as the feature now allows to send FCM notifications without any third party service.