Six months ago, my company wanted to be chosen as “Google Featured”.
So we needed to modify all of the UI/UX in the application that we’re currently serving. I happen to thought the previous application’s architecture was really messy. so I agreed with recreating project and started with a new project.
Unexpectedly, Google has released the Android Architecture Components at that time. So our team was adopted it and applied to a new product project. since released a new product project, I felt need to something clean up to architectures using android architecture components or trendy stacks. So I have clean up a new sample application.
This sample project is based on MVVM clean architecture.
- kotlin based (almost 97%) with anko
- Architecture Components (Lifecycle, LiveData, ViewModel, Room Persistence)
- Material Design & Animations
- Github API
- Dagger2 for dependency injection
- Retrofit2 & Gson for constructing the REST API
- PreferenceRoom for efficient managing SharedPreferences
- RecyclerViewPaginator for api paging
GithubFollows - A demo project based on MVVM clean architecture and material design & animations.
1. Configuring the ViewModel
what is ViewModel? ViewModel is one of the most important things on MVVM architecture. It makes loose coupling between activities and model’s business logic and also makes easier unit testing. Furthermore, it stores data for UI and it’s lifecycle-aware. Within use Dagger2, we can create it easier.
This is sample codes of SearchActivity’s ViewModel. It used dependency Injection @inject with annotation, LiveData and repository patterns.
And next we should create a ViewModel in activity or fragment. but how should we do? ViewModelFactory makes it really easier. It create a new ViewModel and dagger will inject it to activity or fragment with lifecycle-aware. It’s a really wonderful harmony ViewModel and dagger.
And next, we can create the ViewModel just by three line with Dagger!
Inject instances using AndroidInjection.inject(this).
then viewModelFactory who annotated with @inject will be injected with Dagger. next, declare ViewModel using ViewModelProvider. Wow! we created a new ViewModel! How magical?
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.
The Room persistence library provides an abstraction layer over SQLite to allow fluent database access while harnessing the full power of SQLite.
Firstly, we should create a model with @Entity annotation.
And next, we should create DAO(Database Access Object) with @Dao annotation.
Finally, create Database class extends RoomDatabase with @Database annotation. It’s all! and we can use it like below.
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 and business logic that makes more easier to write test codes.
4. Configuring the PreferenceRoom
In case to persist so simple data like username or the last selected menu position, then SharedPreferences are the good alternative to persist data.
I already posted before, PreferenceRoom is for management SharedPreferences more efficiently. It was inspired by Room Persistence and dagger. It supports putter & getter custom functions with security algorithm and put & get objects.
Firstly, we should create an Entity with @PreferenceEntity annotation.
And next, we should create Preference Component and add targets where to injecting dependencies.
Finally, we can request dependency injection using @InjectPreference annotation after initializing components or entity.
PreferenceRoom is based on annotation processor so it creates class file during the compile time.
5. Configuring the DataBinding
The Data Binding Library offers both flexibility and broad compatibility — it’s a support library. DataBinding binds model with xml layout files, so it makes we should not to write messy UI codes on ViewHolders and activities.
add below code on your Gradle file. then setting is done!
enabled = true
then setting is done!
This is a simple history item xml layout. As you can see, it has data tag at the head.
This is a History item’s ViewHolder. drawItemView method binds history data to ItemHistoryBinding.
6. Configuring the RecylcerView Paginator
Sometimes we need to implement endless scroll or paging recyclerView.
So I searched about paging library and I found one by Google.
But It’s only supports paging data from database. So our team implemented RecyclerViewPaginator.
RecylcerViewPaginator performs invoke loadMore when recyclerView needs to load more items. And it would not be called when fetching from network or loading ended.
This is the mainly used architecture in my company’s project!
Of course, I think there are no the best architecture on every projects.
But I think this architecture was really great in my case.
Thank you for reading!