Last Changes
2017/10/20: Updated Architecture Components to 1.0.0-rc1

Firebase Database Setup

If you had used Firebase Database before, you can skip this step. If not, pay attention on the following instructions.

As you watched, Firebase Database is a realtime database with multiple clients. Well, in this article we’ll focus on Android platform.

So, the first step is configure database for Android platform:

1- Install Firebase SDK

2- Add your Android project to Firebase console

3- Add Firebase Database dependency to your app (module’s build.gradle)

compile 'com.google.firebase:firebase-database:11.2.0'

4- Configure Database rules

In this step you can set database access without authentication. Each connections to the database will be without authentication. If not, you have to set a rule to authenticate against database.

5- Write on your database

This is a piece of sample code to write in your Firebase Database from your app:

// Write a message to the database
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("message");

myRef.setValue("Hello, World!");

This will write in a node name “message” (it will be created if it does not exist) with the value “Hello, World!”.

6- Read from your database

You can read any data from your Firebase Database

// Read from the database
myRef.addValueEventListener(new ValueEventListener() {
 @Override
 public void onDataChange(DataSnapshot dataSnapshot) {
 // This method is called once with the initial value and again
 // whenever data at this location is updated.
 String value = dataSnapshot.getValue(String.class);
 Log.d(TAG, "Value is: " + value);
 }

 @Override
 public void onCancelled(DatabaseError error) {
 // Failed to read value
 Log.w(TAG, "Failed to read value.", error.toException());
 }
});

At this point, you’ve set your Firebase Database in your Android app. Next step is create our ViewModel architecture.

Setup ViewModel

If you didn’t hear about Android ViewModel, I recommend you read this postbefore continue this article.

What is ViewModel? It is designed to store and manage UI-related data so that the data survives configuration changes such as screen rotations.

First, you have to add gradle dependencies on your build.gradle:

compile "android.arch.lifecycle:extensions:1.0.0-rc1"
annotationProcessor "android.arch.lifecycle:compiler:1.0.0-rc1"

If you are using support library 26.1.+, you don’t need add runtime dependency. If not, you have to add it:

compile "android.arch.lifecycle:runtime:1.0.0-rc1"

It is easier and more efficient to separate out view data ownership from UI controller logic

public class MyViewModel extends ViewModel {
 private MutableLiveData<List<Article>> articles;
 public LiveData<List<Article>> getArticles() {
 if (articles == null) {
 articles = new MutableLiveData<List<Article>>();
 loadArticles();
 }
 return articles;
 }

 private void loadArticles() {
 // do async operation to fetch articles
 }
}

If the activity is re-created, it receives the same MyViewModel instance that was created by the previous activity. When the owner activity is finished, the Framework calls ViewModel’s onCleated() method so that it can clean up resources.

Create ViewModel and Firebase Database connection

This is the interesting part in this article. Up to now, we’ve set the Firebase Database by one hand and Android ViewModel by other hand. Now is the time of join them and work together.

ViewModel — Firebase Database interaction

 

First, we have to create our repository to manage the Firebase Database event responses.

public abstract class FirebaseDatabaseRepository<Model> {

 protected DatabaseReference databaseReference;
 protected FirebaseDatabaseRepositoryCallback<Model> firebaseCallback;
 private BaseValueEventListener listener;
 private FirebaseMapper mapper;

 protected abstract String getRootNode();

 public FirebaseDatabaseRepository(FirebaseMapper mapper) {
 databaseReference = FirebaseDatabase.getInstance().getReference(getRootNode());
 this.mapper = mapper;
 }

 public void addListener(FirebaseDatabaseRepositoryCallback<Model> firebaseCallback) {
 this.firebaseCallback = firebaseCallback;
 listener = new BaseValueEventListener(mapper, firebaseCallback);
 databaseReference.addValueEventListener(listener);
 }

 public void removeListener() {
 databaseReference.removeEventListener(listener);
 }

 public interface FirebaseDatabaseRepositoryCallback<T> {
 void onSuccess(List<T> result);

 void onError(Exception e);
 }
}

Note we’ve added a method named “addListener” that adds the event listener to firebase database reference.

In our ViewModel, we need to reference to that repository:

private void loadArticles() {
 repository.addListener(new FirebaseDatabaseRepository.FirebaseDatabaseRepositoryCallback<Article>() {
 @Override
 public void onSuccess(List<Article> result) {
 articles.setValue(result);
 }

 @Override
 public void onError(Exception e) {
 articles.setValue(null);
 }
 });
 }

And from our view (a fragment in this case) we have to add an observer to keep data updated:

ArticleViewModel viewModel = ViewModelProviders.of(this).get(ArticleViewModel.class);
viewModel.getArticles().observe(this, new Observer<List<Article>>() {
 @Override
 public void onChanged(@Nullable List<Article> articles) {
 recyclerView.setAdapter(new ArticleAdapter(articles));
 }
});

Full sample

You can review the full sample from the following repo.

Feel free to comment and add any suggestions!