MVVM on Android Crash Course – Kotlin & Android Architecture Components

Model – View – ViewModel is an architectural pattern which will empower you to write manageable, maintainable, cleaner and testable code. MVVM is also supported and encouraged by Google itself. There are many first-party libraries like lifecycle-aware components, LiveData, ViewModel and many more.

In the previous post, you learned the theory behind MVVM. If you haven’t read it yet, I recommend you to do so as I will skip explaining the “big picture” in this tutorial.

Today you are going to put MVVM pattern into practice. You will build a simple, yet real-enough app which will make you understand MVVM on a deeper level. It will be an app displaying quotes which you put in. This quote app will have a ViewModel, Repository, fake database and a simple dependency injection. This will give you a strong foundation to build on.

Do you prefer video tutorials?

 

?Get the code from this tutorial?

Starting out

Create a new Android project with an Empty Activity as the starting point. Also make sure that you select Kotlin as the default language. The name of the launcher Activity should be QuotesActivity.

With the project created, let’s get into importing a bunch of libraries. Open build.gradle for the app module. And add the following packages. Keep in mind that the versions will change in the future, so keep them up to date.

This tutorial is not focused on building a nice UI  so this is what I came up with. The QuotesActivity will have a TextView which displays all the quotes, two EditTexts for adding new quotes and a button. There is no RecyclerView for the sake of simplicity.

activity_quotes.xml

Project structure

Before you get started writing code, it’s important to organize things into packages in a way that makes sense. This is how the project structure will look like once you have all the classes created. For now, it will be enough that you have the packages and also move QuotesActivity to ui.quotes package. Later, when you are creating new classes, refer to this picture to find their package if you’re not sure.

Making the Quote data class

This whole app is centered around quotes so it’s probably a good idea to create a class representing a single quote.

Data Access Object – DAO for Quotes

When you have a Quote object in memory, you’d usually want to store it in a database to make it persist when the app is closed. You could use any kind of a database from Cloud Firestore to local SQLite or you could even set up your own backend, communicate with it through an API and use SQLite as a local cache. If you want to use SQLite in your real apps, check out a library called ROOM. It will make your life easier.

In the world of ROOM, anytime you want to do something in a database, you do it through a DAO. Under normal circumstances, a DAO is an interface defining all allowed actions which can happen for a table in the database, like reads and writes.

However, this tutorial is focused on the core concepts of MVVM architecture. Adding a real database of any kind would be only unnecessarily creating complexity. This is why you will use a fake database and a fake DAO which will save data to a MutableList. You are not going to skip any important steps which are present in production apps and the code will be simple at the same time.

Database class as a container for DAOs

In a production app you will surely have more than one DAO. For example, in a chat app you may keep track of the users and also of user groups. There you have already 2 DAOs.

To put all of the data access objects in one place you should create a database class. If you are using the ROOM library, having a database class is actually required.

Because it doesn’t make sense to have 2 instances of database at the same time, a database class will be a singleton. Kotlin has a nice syntax for singletons where instead of class you write object. While this would be sufficient in our case, it usually isn’t for production apps. When you use the object keyword, you don’t have a chance to pass something into the class’ constructor. In the case of ROOM, you need to pass an application context to your database. To circumvent this problem, you have to create singletons the Java way even in Kotlin.

Repository as a point of control

Repositories are classes which do all of the decision making regarding app’s data. Should you fetch new data from the server or is it enough to use the local data? Do you need to keep 5 days of weather data localy or only 3 days? Making such decisions is the job of a repository.

I know, having a repository class in this particular project may seem redundant – you only have a single DAO and you don’t even have a backend. While this is true, this doesn’t stop you from learning about the core work repositories have to do – being the single source of truth for all the data which ViewModels request.

Again, it doesn’t make sense to have multiple repository objects, so it will be a singleton. This time you need to pass in the FakeQuoteDao for repository to fulfill its role. You will use dependency injection to supply this FakeQuoteDao instance to the repository.

Getting closer to user interface

You have done quite a bit of work already. Now it’s time to connect what you created to the “view” part of MVVM, in this case the QuoteActivity. Activities and Fragments are merely for displaying things on the screen and for handling user input. All of the logic, data, manipulation with the data goes to a ViewModel. Then the View only calls functions on the ViewModel. This way, the data doesn’t get reset when an orientation change occurs and so on.

Alright! Now get the dependency injection going, then jump right into the QuotesActivity and make things work! Ummm, not yet. As you can see, QuotesViewModel requires a repository to function and that repository is passed into the constructor. The way that ViewModels are created / gotten from ViewModelProvider (to prevent recreation on, say, orientation changes)  requires a ViewModelFactory class. You simply cannot create ViewModels directly, instead, they are going to be created in a factory.

Dependency injection ?

As I’ve already briefly mentioned, dependency injection is a way to modularize your code. In production, you want your ViewModel to operate with a real repository which is fetching data from servers and all that. However, when you are just testing your ViewModel, it’s a good idea to provide it with only some dummy data so that you can control everything in your tests.

If you were to instantiate objects directly in each class, providing dummy data for testing (aka mocking) would be hard if not impossible. You would need to change every single constructor call in every class you want to test. Instead, you can create all of the dependencies in one place. Then if you need to test something, you know where and what to change – only one class which constructs all of the dependencies.

This is a simple but at the same time effective form of dependency injection. Feel free to use a framework like Dagger2 for really complex projects.

Finishing up with the view

By now you have already created everything except for the view with which the user can interact. It may not seem like it in this simple project, but normally, your views will seem tiny compared to the other classes. That’s because views in MVVM handle only the least possible amount of data which they immediately pass to / get from the ViewModel.

Conclusion

This is it! You just created your very first MVVM Android app in Kotlin. Let all the new information digest for a while and come back for more app tutorials. In the near future you will also learn how to create fully-fledged apps using MVVM architecture.  Those apps will include a real database ?

 

Leave a comment


This site uses Akismet to reduce spam. Learn how your comment data is processed.


soulduse

3 months ago

Thank you for explaining for MVVM easily

you missed “http:” inside xml 🙂

Matej Rešetár

3 months ago

Oh, it must be a problem with the syntax highlighter ?

Omprakash Kolluri

3 months ago

Like this post. Experimenting with it. Ready to learn when you have more to share. Thank you

Roshan

3 months ago

getting error following errors
1. ForEach statement in QuoteActivity: Only safe or non-null asserted calls are allowed on a nullable receiver of type list
2. FakeDatabase : @Volatile private var instance: FakeDatabase? = null: Platform Declaration Clash

Matej Rešetár

3 months ago

Hello! For the first problem, try changing “.” to “?.” for the forEach.
As for the second declaration clash, I’m actually wondering why I didn’t get it ? Change “instance” to “_instance”. There is a clash with the automatically generated getInstance() for the property and getInstance() which we’ve created ourselves.

D Kiran Kumar

3 months ago

Excellent tutor, required full tutorial explaining hitting REST API, Local Storage, Repository, ViewModel, View

abi

3 months ago

Great tutorial.

By the way, how do you test it? I mean mocking livedata and viewmodel and test it for unit test or instrumented test.

Thank you

Jewel Rana

1 month ago

please help me i can not bind room database with kodein

Faisal

3 weeks ago

great lessons but can you please give a brief tutorial from start and in sequence. That’ll help alot!

Matej Rešetár

3 weeks ago

Hello! You can watch my tutorial series where we’re creating a MVVM forecast app. This is the first part: https://resocoder.com/forecast-app-01

Development made simple

We're here to help you. If you have any questions, let us know.

Copyright 2017 - 2018 Reso Coder © All Rights Reserved