Introduction to MVVM

Alok Verma
MindOrks
Published in
3 min readFeb 10, 2019

I know it’s a bit late to talk about android architecture components as nowadays every app is adapting this pattern as its Android first official architecture components.

In this article, we will talk about what is Model View View Model(MVVM) pattern, how its different from another design pattern like MVP etc. Then we will show how Live Data and View Models work with the help of code. Then we will move to real implementation in which we will fetch some movies listing from TMDB database for demo purpose.

What is MVMM-

if you are already familiar with MVVM, you can directly jump to code to understand how to implement in our applications. MVVM consists of three things- Model, View and ViewModel. Each component has its own responsibilities to do their task

Model - In the model layer, we write our business logic

ViewModel- This layer basically interacts with view and model and provide observable(Live Data in case of my example, you can use any observable) which is observed by the view that is fragment and activity.

View- As the name suggests, the view is our fragment and Activity. View observe the view model observable to update its element.

Difference between MVP and MVVM-

In MVVM, we don't have to pass view reference to the view model to update view from the view model, View model has observable that view observe and we use LiveData observable which is LifeCycle Aware so we don't need to take care of views lifecycle to update the view.

but in case of MVP, we pass view reference to the presenter to update the view, so presenter is bound to view’s lifecycle which can lead to lots of boilerplate code to make lifecycle aware.

Enough of talk now we move to code.you can check my repo for the complete code-

In this example, we are using TMDB open source API for fetching movies details. Our model is-

class MoviesRepository {

/*
* method to fetch top rated movies
* */

fun fetchTopRated(key: String, page: Int): MutableLiveData<MoviesItem> {
val data = MutableLiveData<MoviesItem>()
RetrofitClient.getInstance().apiService.getTopRatedMovies(key, page).enqueue(object : Callback<MoviesItem> {
override fun onFailure(call: Call<MoviesItem>, t: Throwable) {
}
override fun onResponse(call: Call<MoviesItem>, response: Response<MoviesItem>) {
data.value = response.body()
}

})

return data
}

private fun throwError(throwable: Throwable?) {
Log.e("tag", throwable.toString())
}


}

Our ViewModel is-

class MoviesViewModel(val repo: MoviesRepository) : ViewModel() {
fun getTopRatedMovies(key: String, page: Int):MutableLiveData<MoviesItem> {
return repo.fetchTopRated(key,page)
}
}

As you see, in our repository we have written logic to fetch the data from network calls and our ViewModel fetch data from the repo and return LiveData which is observed by our view like this -

private fun initializeUI() {
val factory = InjectorUtils.provideQuotesViewModelFactory()
val viewModel = ViewModelProviders.of(this, factory)
.get(MoviesViewModel::class.java)

viewModel.getTopRatedMovies(ApiConstants.API_KEY, 10).observe(this, Observer { quotes ->
val stringBuilder = StringBuilder()
quotes.results.forEach { quote ->
Log.e("TAG", quote.originalTitle)
stringBuilder.append("${quote.title}\n\n")
}
text.text = stringBuilder.toString()
})

}

For more understanding of code, how to create ViewModel, ViewModelFactory and provide a dependency of the repository to ViewModel, please go through my GitHub repository.

Thanks,

Alok V.

--

--

Alok Verma
MindOrks

Sr. Software Engineer @OYO, Cinema fanatic, Technology enthusiast.