Modern Android development with Kotlin (Part 2)
The second part of the Modern Android development with Kotlin article series.
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
- add ProgressBar that will be visible only if isLoading 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
- add RecyclerView in our activity_main.xml 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
- 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
- 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
- We click on button
- While we are waiting for data change, MainActivity can be recreated due to configuration changes.
- Our MainViewModel is still alive.
- After 2 seconds, repositories 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:
Why I prefer MVVM over MVP?
- There is no boring interface for View cause ViewModel does not have reference to View.
- There is no boring interface for Presenter and there is no need for it.
- It is much easier to handle configuration changes
- Using MVVM, we have less code in Activities, Fragments etc.
Repository Pattern

As I said earlier, Model is just an abstraction name for the layer where we prepare the data. Usually, it contains repositories and data classes. Each entity (data) class should have corresponding Repository class. For example, if we have User and Post data classes we should also have UserRepository and PostRepository. All data should come directly from it. We should never call Shared Preferences instance or DB instance from View or from ViewModel.
So, we can rename our RepoModel to GitRepoRepository where GitRepo comes from Github Repository and Repository comes from Repository pattern.
Ok, MainViewModel gets list of Github repositories from GitRepoRepsitories, but where GitRepoRepositories get from?
You can make call on your client instance or DB instance directly in repository, but it is still not a good practice. Your app should be modularized as much as you can make it. What if you decide to use different client, to replace Volley with Retrofit? If you have some logic inside, it will be hard to refactor it. Your repository doesn’t need to know which client you are using to fetch the remote data.
- The only thing that repository needs to know is that the data is coming from remote or local. There is no need to know how we are getting those remote or local data.
- The only thing that ViewModel needs is the data
- The only thing that View should do is to show that data
When I was starting Android Development, I was wondering how apps work offline and how that syncing of data works. Good Architecture of the app allows us to make it with ease. For example, When loadRepositories in ViewModel is called, if there is internet connection, GitRepoRepositories can get the data from remote data source and save it in local data source. Once when phone is in offline mode, GitRepoRepository can get the data from local data source. So, Repositories should have instances of RemoteDataSource and LocalDataSource and logic that handle where data should come from.
Let’s add local data source:
Here we have two methods: first that returns us fake local data and second for fake saving of the data.
Let’s add remote data source:
This one just has a method that returns fake remote data.
And now we can add some logic to our repository:
So, separating sources we can save data locally with ease.
What if you only need data from network, do you still need to use repository pattern? Yes. It makes your code easier for testing, other developers can understand your code better and you can maintain it faster! :)
Android Manager Wrappers
What if you want to check internet connection in the GitRepoRepository so you can know which data source to ask for data? We already said that we should not place any Android related code in ViewModels and Models, so how to handle this problem?
Let’s make wrapper for internet connection:
This code will work only if we add permissions in manifest:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
But how to make instance in Repository cause we don’t have context? We can ask for it in constructor:
We made before a new instance of GitRepoRepository in ViewModel. How can we now have NetManager in ViewModel cause we need a context for NetManager? You can use AndroidViewModel from Lifecycle-aware components library that has context. That context is context of the application, not of an Activity:
In this line:
constructor(application: Application) : super(application)
we are defining constructor for MainViewModel. This is needed cause AndroidViewModel asks for Application instance in its constructor. So in our constructor, we are calling super method so constructor of AndroidViewModel, that our class will extend, will be called.
Note: We can save us from 1 line if we do:
class MainViewModel(application: Application) : AndroidViewModel(application) {
...
}
Now, when we have instance of NetManager in GitRepoRepository we can check for internet connection:
So if we have internet connection we will get remote data and save it locally. On another side, if we do not have internet connection we will get local data.
Kotlin Note: operator let checks nullability and returns you a value inside it.
In one of the following articles, I will write about dependency injection, why it is bad to make instance of repository there in ViewModel and how to avoid using of AndroidViewModel. Also, I will write about more problems that we have in the code up to this point. I left them for reason... :)
I am trying to face you to the problems so you can understand why all those libraries are popular and why you should use it.
P.S. I changed my mind about mappers. I decided to cover it in of the following articles.
Part 3:
Thanks for reading and follow me for more.