Android MVVM Architecture Components using The Movie Database API.

Jaewoong Eum
The Movie Database

This posting is about how to implement android project based on mvvm architecture using the movie db API. I wanted to implement a simple example project using an open API. But thankfully, we can use movies API for free at the movie db. So I used that and made public a simple project.

This simple project is based on MVVM architecture. And written Unit Test code about business logic.

  • 100% kotlin based with anko
  • Architecture Components (Lifecycle, LiveData, ViewModel, Room Persistence)
  • Material Design & Animations
  • The Movie DB API
  • Dagger2 for dependency injection
  • Retrofit2 & Gson for constructing the REST API
  • BaseRecyclerViewAdapter for implementing adapters and viewHolders
  • Mockito-kotlin for Junit mock test
  • etc..

How to build on your environment

If you want to build the sample project after fork on your computer, you should get an API key from The Movie DB. And add your API key in local.properties file like below.

tmdb_api_key = YOUR_API_KEY

Development Process

This project is not actually 100% TDD, but I tried a little bit to write Unit Test codes.

development process
  1. API Service -> API Service Unit Test with api response mock files
  2. DAO -> DAO Unit Test
  3. Repository -> Repository Unit Test
  4. ViewModel -> ViewModel Unit Test
  5. DI & Refactoring
  6. Implmentating UI & Layouts

Architecture

Based on mvvm architecture and repository pattern.

architecture

1. Configuring the ViewModel

ViewModel is one of the most important things on MVVM architecture. Unlike MVP architecture, it makes loose coupling between activities and business logic. ViewModels does not have dependencies of UI components. So It makes easier unit testing. And ViewModel holds data about UI and it is lifecycle-aware. It makes easier implementing landscape mode, and we do not need to release observers when UI component be destroyed.

TvDetailViewModel requests dependency injection using @inject annotation. The constructor receive only a repository, So ViewModel does not know about actual business logic like how-to-get or how-to-save. It makes easier unit testing to ViewModel. And ViewModel just publish data or get data from UI components using LiveData. LiveData holds data from repository(fetching from network or getting from DB), it makes easier implementing landScape screen mode. And next, we should create a ViewModel in activities or fragments. but how should we do? ViewModelProvider.Factory makes it really easier.

AppViewModelFactory

And next, we can create the ViewModel just by three line with Dagger!

MainActivity Example

Inject instances using AndroidInjection.inject(this).
then viewModelFactory who annotated with @inject will be injected by Dagger. next, declare ViewModel using ViewModelProvider. Wow! we created a new ViewModel!

2. Configuring the Room Persistence

Room is one of the popular database library using SQLite made by Google.
IMO, Room has many advantages. It persists data over configuration changes, based on Objected-Oriented Modeling, supports migration, and it has really nice synergy with LiveData or Rxjava.

The Room persistence library provides an abstraction layer over SQLite to allow fluent database access while harnessing the full power of SQLite.

Movie Entity Model

Firstly, we should create an entity model with @Entity annotation.

MovieDao

And next, we should create DAO(Database Access Object) with @Dao annotation.

AppDatabase

Finally, create Database class extends RoomDatabase with @Database annotation. It’s all! and we can use it right now.

3. Configuring the Repository

Repository is one of the design pattern, defined by Eric Evens. It is one of the most useful and most widely applicable design patterns ever invented. Domain layer request needed data to repository, and repository tosses data from local repositories like database or SharedPreferences. It makes loose coupling between ViewModel, so easier writing unit test code to ViewModel and business logic.

DiscoverRepository

@Singleton annotation makes DiscoverRepository can be injected by Dagger. And requests dependency injection using @inject annotation on the constructor.So we can get network service and DAO singleton instances without initializing by yourself.

4. Unit Testing

If we can, TDD is the best. Or not, we should write unit test codes. Unit Testing provides numerous benefits including finding software bugs early, facilitating change, simplifying integration, and providing a source of documentation. In this project, I used mockito-kotlin.

MovieRepositoryTest

mockito-kotlin include original mockito library. And it has some nice expression about verify like whenever than `when`. I did Unit Testing about Api Services, DAO, ViewModels, Repositories or etc.

5. Implementing Circular Revealed Animation

I implemented Activity Extension for using circular revealed animation on activities.

ActivityExtension

Circular revealed animation can be used over API 21. So we have to check device version before using. As you can see, requestGlideListener extension is for use with Glide.

Glide listener

That’s all!

If this posting was helped, please give a star at GitHub!

Jaewoong Eum

Written by

A software engineer: Android, IoT. Interested in Psychology, Magic Tricks and writing poems. https://github.com/skydoves

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade