Unlock your Android ViewModel power with Koin
Google has made a very nice gift with its Android Architecture Components. Now we have in hands tools and power to write more elegant and more structured API. The Koin framework can give you a good help to get most of those Architecture Components. Let’s see how 👍 — (updated for Koin 0.9.1)
Some months ago I was writing about Koin, as a good alternative to Dagger dependency injection solution and how it’s easy to write your dependency injection with it. The Google blueprint TODO application was developed with MVP patterns approach in this version. Today the Architecture Components arsenal can easily push our apps to the MVVM Architecture grade.
I won’t show you how to rewrite the TODO application in MVVM style (you will find dedicated branches for it), but I recommend some very good lectures and videos on the subject:
- Articles and videos from Florina Muntenescu — Android Architecture Patterns Part 3: Model-View-ViewModel, https://medium.com/upday-devs/android-architecture-patterns-part-3-model-view-viewmodel-e7eeee76b73b
- Articles & Videos from Lyla Fujiwara — https://www.youtube.com/watch?v=c9-057jC1ZA & https://www.youtube.com/watch?v=jCw5ib0r9wg
- Android Architecture Components Official documentation
Instead, I propose to see together the latest feature from Koin, which brings injection dependency for your ViewModel classes and makes life easier with it.
In this article, the screenshots are extracted from an MVVM Weather sample app. The sources can be found on koin-samples@github.
Firstly, check that you have the following Gradle dependency:
Quick and easy declaration
Without Koin, your ViewModel would be created with:
val model = ViewModelProviders.of(this).get(DetailViewModel::class.java)
With the koin-android-architecture module, we gain a more compact declaration with “getViewModel()”:
val model = getViewModel<DetailViewModel>()
or even a lazy property declaration with “by viewModel()”:
val model by viewModel<DetailViewModel>()
That’s it! Nothing particular to add to your Activity or Fragment. Your ViewModel component is ready to be injected by Koin.
Just a ViewModel class
Your class must obviously extend the Android ViewModel class. Use its constructor for dependency injection:
Nothing particular to add to your ViewModel class. Koin will inject the needed dependencies via its constructor (here our weatherRepository instance).
Write a Koin module and declare your ViewModel component using the “viewModel” keyword:
Our DetailViewModel is now ready to go! Just start Koin as usual.
Need to share your ViewModel between Activity/Fragments? No problem, just declare it with lazy properties like below:
The Activity and Fragment above will share the same instance of ResultViewModel. Fragment use the lazy delegate property with “by sharedViewModel()”
Ready to test!
You are now ready to make unit test with it! (bring the koin-test module) 🌈 Of course, your class can be unit tested with mock (constructor injection). But we can also make a KoinTest class to make an “integration” test and reuse our ViewModel and Repository.
Here below, a test setup to inject components from our app module. Use the “by inject()” properties to declare lazy injected components. We will mock the View side for our ViewModel.
Nice. This will allow us to directly use our repository with real data! Below we mock an observer, and make it observe changes from our ViewModel.