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)

DataBinding

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

API Service -> API Service Unit Test with API response mock files DAO -> DAO Unit Test Repository -> Repository Unit Test ViewModel -> ViewModel Unit Test DI & Refactoring Implementing UI & Layouts

Architecture

Based on MVVM architecture and repository pattern.

architecture

1. Configuring the ViewModel

ViewModel is one of the most important things in MVVM architecture. Unlike MVP architecture, it makes the 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 the UI component is destroyed.

TvDetailViewModel requests dependency injection using @inject annotation. The constructor receives 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 publishes data or get data from UI components using LiveData. LiveData holds data from the repository(fetching from the 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 lines 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

The 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 the 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 verifying 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 the 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!