It is really hard to find one project that covers all the things that are new in Android Development, so I decided to write one.

In this article we will use the following:

0. Android Studio 3, beta 1 Part 1

1. Kotlin language Part 1

2. Build Variants Part 1

3. ConstraintLayout Part 1

4. Data binding library Part 1

5. MVVM architecture + repository pattern + Android Manager Wrappers

6. RxJava2 and how it helps us in architecture Part3

7. Dagger 2.11, what is Dependency Injection, why you should use it Part4

8. Retrofit (with Rx Java2)

9. Room (with Rx Java2)

5. MVVM architecture + repository pattern + Android Manager Wrappers

Little bit about Architecture in Android World

For a long time, Android developers didn’t have any kind of architecture in their projects. In the last three years, Architecture got a lot of hype in the Android developers community. The time of God Activity passed and Google published Android Architecture Blueprints repository with a lot of samples and instructions about different architectural approaches. Finally, at Google IO ’17 they introduced Android Architecture Components, a collection of libraries to help us have cleaner code and better apps. Component describes that you can use all of them or just some of them. Though, I find all of them really useful. In the following text and in the following parts we will use those components. First, I will code up to the problem, then refactor code using those components and libraries to see what problems those libraries will solve.

There are two main architectural patterns that separate GUI code:

MVP

MVVM

It is hard to say what is better. You should try both and decide. I prefer MVVM using lifecycle-aware components and I will write about it. If you never tried MVP, there is a bunch of good articles on Medium about it.

What is MVVM pattern?

MVVM pattern is an architectural pattern. It stands for Model-View-ViewModel . I think that name confuses developers. If I was the one who named it, I would give it a View-ViewModel-Model name cause ViewModel is the one in the middle that connects View and Model.

The View is abstraction name for your Activity, Fragment or any other Android Custom View. Take note that it is really important to not misplace this View with Android View. The View should be dumb and we should not write any logic in our View. The View should not hold any data. It should have ViewModel instance reference and all data that is needed should come to View from it. Also, View should observe on those data and layout should be changed once when data from ViewModel is changed. To conclude, View has a responsibility: how the layout looks for different data and states.

The ViewModel is abstraction name for the class that holds data and has logic about when the data should be fetched and when the data should be presented. ViewModel holds the current state. Also, ViewModel has reference to one or more Model instances and all the data should be got from those. It should not know, for example, are the data coming from database or remote server. Further, ViewModel should not know about the View at all. Moreover, ViewModel should not know anything about Android framework at all.

The Model is abstraction name for the layer where we prepare the data for ViewModel. It is the class where we will get our data from remote server and cache it in memory or save it in the local database. Note that it is not the same as those: User, Car, Square etc. model classes that just hold the data. Usually, it is an implementation of Repository pattern which we will cover in the following text. Model should not know about ViewModel.

MVVM, if implemented right, is a great way to separate your code and make it more testable. It helps us to follow the SOLID principles so our code is easier to maintain.

The Code Example

Now I will write the simplest example that explains how it actually works.

At first, let’s make our simple Model that returns us some string:

Usually, getting the data is the async call so we have to wait for it. To simulate it I have changed the class to the following:

First, I have made OnDataReadyCallback interface that has function onDataReady. Now, our refreshData function takes the implementation of OnDataReadyCallback. To simulate waiting I have used Handler. Once when 2 seconds passed, onDataReady function will be called on the implementation of OnDataReadyCallback.

Let’s now make our ViewModel

As you can see, there is an instance of RepoModel, text that we will show and isLoading boolean to hold a current state. Now, let’s make a refresh function that will be responsible for getting the data:

refresh function makes a refreshData call on the instance of RepoModel that takes implementation of OnDataReadyCallback. Ok, but what is object? Whenever you want to implement some interface or extend some class without creation of subclass you will use object declaration. What if you want to use is it as an anonymous class? In that case, you have to use object expression:

When we call refresh, we should change view to loading state and once when data come, we should set isLoading to false.

Also, we should change text to ObservableField<String> and isLoading to ObservableField<Boolean>. ObservableField is a class from Data Binding library that we can use instead of creating an Observable object. It wraps the object that we would like to be observed.

Note that I used val instead of var cause we will only change value in field, not field itself. And if you want to initialize it you should do:

Let’s change our layout so it can observe on text and isLoading. First, we will bind MainViewModel instead of Repository:

Then, let’s :

change TextView to observe on text from instance of MainViewModel

from instance of add ProgressBar that will be visible only if isLoading is true

is true add Button that on click will call refresh function from instance of MainViewModel and be clickable only if isLoading is false

If you run this you will get error cause View.VISIBLE and View.GONE cannot be used if View is not imported. So, we have to import it:

Ok, that’s it with layout. Now we have to finish binding. As we said View should have instance of ViewModel:

Finally, we can run it:

You can see that old data is changed to new data.

This was the simplest MVVM example.

There is one problem about this, let’s rotate the phone now:

new data is returned to be old data. How is it possible? Take a look to Activity lifecycle:

Once when you rotate the screen new instance of Activity is created and onCreate() method is called. Now, take a look at our activity:

As you can see, once when a new instance of Activity is made, one instance of MainViewModel is made too. Should it be nice if somehow we can have the same instance of MainViewModel for each recreated MainActivity?

Introducing Lifecycle-aware components

Because a lot of developers faced this problem, developers from Android Framework Team decided to make library that will help us to solve it. ViewModel class is one of them. It is the class that all our ViewModels should extend from.

Let’s make our MainViewModel to extend ViewModel from lifecycle-aware components. First, we should add that lifecycle-aware components library in our build.gradle file:

Now, make our MainViewModel to extend ViewModel:

And in onCreate() function of MainActivity you should have:

Note that we are not making new instance of MainViewModel. Now, we are getting it from ViewModelProviders. ViewModelProviders is Utility class that has methods for getting ViewModelProvider. It is all about scope. So, if you call ViewModelProviders.of(this) in Activity then your ViewModel will live until that Activity is alive (destroyed and not recreated) . Hence, if you call it in Fragment then your ViewModel will live until that Fragment is alive and so on. Take a look at the diagram:

ViewModelProvider is responsible to make new instance if it is called first time or to return old instance once when your Activity/Fragment is recreated.

Don’t allow to be confused with:

MainViewModel::class.java

In Kotlin, if you just do:

MainViewModel::class

It will return you a KClass and it is not same as Class from Java. So, if we do: .java by documentation it:

Returns a Java Class instance corresponding to the given KClass instance.

Let’s now see what will happen if we rotate the screen:

We have same data as we had before rotation.

In the last article, I said that our app will fetch list of Github Repository and show it. To make it, we have to add getRepositories function that will return fake list of repositories:

Also, we should have a function in our MainViewModel that will call getRepositories from RepoModel:

And at the end, we should show those repositories in RecyclerView. To do it, we will have to:

make rv_item_repository.xml layout

layout add RecyclerView in our activity_main.xml layout

in our layout make RepositoryRecyclerViewAdapter

set adapter to recyclerview

To make rv_item_repository.xml I used CardView library, so we need to add it in build.gradle (app) :

implementation 'com.android.support:cardview-v7:26.0.1'

and here is how it looks:

Next step is to add RecyclerView in activity_main.xml. Before doing it, don’t forget to add RecyclerView library:

implementation 'com.android.support:recyclerview-v7:26.0.1'

Note that we deleted some TextView elements from before and button now triggers loadRepositories fun instead of refresh:

Let’s delete refresh function in MainViewModel and refreshData function from RepoModel cause we don’t need them anymore.

Now, we should add Adapter for our RecyclerView:

Note that ViewHolder takes instance of RvItemRepositoryBinding type instead of View type so we can implement Data Binding in ViewHolder for each item. Also, Don’t be confused by following oneline function :

override fun onBindViewHolder(holder: ViewHolder, position: Int) = holder.bind(items[position], listener)

It is just shorter way to write:

override fun onBindViewHolder(holder: ViewHolder, position: Int){

return holder.bind(items[position], listener)

}

And items[position] is implementation of indexing operator. It is same as items.get(position).

One more line that can confuse you is:

binding.root.setOnClickListener({ _ -> listener.onItemClick(layoutPosition) })

You can replace parameter with _ if you don’t use it. Nice, huh? :)

We added adapter but we still did not set it to our recyclerView in our MainActivity :

Let’s try it:

This is strange. What happened here?

Activity is created, so new adapter is created with repositories that are actually empty

that are actually empty We clicked on button

loadRepositories function is called, progress is shown

after 2 seconds, we got repositories, progress is hidden but repositories are not. It is because notifyDataSetChanged is not called on adapter

is not called on adapter Once we rotate the screen, new activity is created so new adapter is created with repositories parameter that actually has some items

So, how MainViewModel should notify MainActivity about new items, so we can call notifyDataSetChanged ?

It should not.

This is really important, MainViewModel should not know about MainActivity at all.

MainActivity is the one who has instance of MainViewModel, so it is the one that should listen for changes and notify Adapter about changes.

But, how to do that?

We can observe on repositories, so once when data is changed we can change our adapter.

And what can be wrong with that solution?

Let’s look into the following case:

In MainActivity, we observe for repositories : once when change happens, we do notifyDataSetChanged

: once when change happens, we do We click on button

While we are waiting for data change, MainActivity can be recreated due to configuration changes.

can be recreated due to Our MainViewModel is still alive.

is still alive. After 2 seconds, repositories field gets new items and notify observer that data is changed

field gets new items and notify observer that data is changed observer tries to do notifyDataSetChanged on adapter that doesn’t exist anymore cause MainActivity is recreated.

So, our solution is not good enough.

Introducing LiveData

LiveData is another Lifecycle-aware component. It is basically observable that knows about lifecycle of the View. So, once when activity is destroyed because of configuration changes, LiveData knows about it, so it destroys observer from destroyed activity too.

Let’s implement it in our MainViewModel:

and observe for changes in MainActivity:

What is meaning of it keyword? If some function has only one parameter, then that parameter can be accessed by keyword it. So, let’s say that we have lambda expression for multiplication by 2:

((a) -> 2 * a)

We can replace it with

(it * 2)

If you run it now, you can see that everything works: