Sign in Go Pro

Android Model-View-ViewModel Pattern

Building the Model- The Origin of the Data


Up next



The model is the core of an MVVM application. It is where the data, state and business logic of the application lives. This lesson will teach you how to how to create a model from scratch. The model is built up further throughout this course, but this will give us a solid foundation from which to start.

In this lesson you will learn:

  • How to create a model from scratch in a new Android application.
  • How to use a test driven approach to build your model and ensure it works as designed.
  • Benefits of using Kotlin data objects for your data model classes.


Do we always have to make sure the model and the test inside the same package (model)?

You don't absolutely have to keep your test and the model class you are testing in the same package, but it's a good idea to mirror the packages generally.

In terms of the package "model", it's not important that you name the package that your models live in as model, but it helps with organization. In some applications, you may end up grouping Models, Views and ViewModels by functionality type.

For example, if you had a more fully featured app that had lots of different functionality like calculate tips, make reservations, order take out, then instead of : com.acme.tipcalculator.model, com.acme.tipcalculator.view, com.acme.tipcalculator.viewmodel

You might have :, com.acme.tipcalculator.reservations, com.acme.tipcalculator.takeout, each with Models, Views and ViewModels underneath. In such a case, it's still a good practice to have the tests for each, mirror the package of the class they're testing.

Hey Eric, I am trying to build the app, but this error happens:

"Could not download asm.jar (org.ow2.asm:asm:6.0): No cached version available for offline mode"

Hi Rodrigo,

I'm not able to reproduce this, but from the error string there it looks like your Gradle build may be running in offline mode.

If you go into Preferences -> Build, Execution, Deployment -> Gradle, you should see a checkbox with the label "Offline Work", make sure that is unchecked. After you save the setting, try to rebuild the project by going to Build -> Rebuild Project.

On other thing I noticed is that, the asm dependency is used by and, but I noticed when I build the project, the project pulls in org.ow2.asm:asm:5.1. Sometimes when I open a project in Android Studio, a prompt says "Android Gradle Plugin Update Recommended". I would recommend against doing that for the sake of this course. When you say yes, Android Studio usually does a good job at updating dependencies, but occasionally requires manual updates to the build.gradle files to get everything working. This may not apply to you in this case. I only mention it because I saw your version of the asm dependency is different than what I see when I build the project.

I hope this helps.

Now works.

Here what I did to fix:

1) Replaced in app/build.gradle:
implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"

2) Replaced in build.gradle:
kotlin_version = '1.2.21'
kotlin_version = '1.3.0'

Now I am getting errors in DataBinding:

Hi Rodrigo,

It sounds like your project build.gradle files may be out of sync with the sample, but I think in this case, the data binding error you see may be resolved by removing this line kapt "$android_plugin" from your app/build.gradle file. After that, sync your dependencies, clean and rebuild.

It's no longer required to declare that dependency explicitly after build tools plugin 3.2.0+, which I think you are using. And if you do declare it, and it doesn't match the build tools plugin you're using, it can cause errors with using data binding annotations.

Let me know if that fixes it!

Hello Eric.
I was trying to run this RestaurantCalculatorTest.kt. But look, it is not working:
Maybe is the rounding feature.
Could you give me a hint here?

Hi Rodrigo,
It looks like you're missing a set of parentheses in your calculator, in the tipAmount calculation. I've copied the correct version here for comparison.

val tipAmount = (checkAmount * (tipPct.toDouble() / 100.0)) // <-- Notice the wrapping parens
.setScale(2, RoundingMode.HALF_UP)

You can see the reference implementation here.

I should point out that in a production app, you'd want to work with BigDecimal (not doubles and ints) when working with money, but the goal of this course was mainly to explain the MVVM pattern, so I tried to keep it simple. :-)

Thanks for watching and let me know if you have anymore questions.


Not it works.
Thanks Eric!!!

Awesome 🙌

Hello Eric,

A quick question on the Kotlin code, I have come with very minimal understanding on Kotlin. Here in the RestuarantCalculator class when we return the values, I just did
TipCalculation(checkAmount, tipPct, tipAmount, grandTotal) where as I see that you do
TipCalculation(checkAmount = checkAmount, tipPct = tipPct, tipAmount = tipAmount, grandTotal = grandTotal)

Is there a significance of doing this your way?

Hi Saravanan,

Your way is just fine too! I'm using a Kotlin language feature called, named arguments, to be more explicit at the call site about which arguments I'm setting. But, it's just a matter of preference.

One thing I should note, although I'm not taking advantage of it in the lesson, named parameters also allow you to provide arguments in any order from the caller. For example, the following 2 lines are equivalent, both producing a TipCalculation instance with the same values.

TipCalculation(checkAmount = checkAmount, tipPct = tipPct, tipAmount = tipAmount, grandTotal = grandTotal)
TipCalculation(grandTotal = grandTotal, tipAmount = tipAmount, tipPct = tipPct, checkAmount = checkAmount)



Lessons in Android Model-View-ViewModel Pattern