Delegate your lifecycle occasions to your ViewModel
ViewModels exist to remove all enterprise logic from the View. Regardless of the way you architect your ViewModel, some logic stays tightly certain to the View’s lifecycle. For example, a small use-case can be to carry out some monitoring every time you open a display. Assuming this display injects a ViewModel, and this ViewModel rightfully owns the monitoring logic, then you definately’ll have to detect when to set off such motion.
Because the lifecycle belongs to the View’s realm, you possibly can go away this to the View’s duty — overriding the
onResume perform as an example.
However let’s not overlook why we’re utilizing ViewModels. Ultimately, we imply to extract this enterprise logic into the ViewModel to check it. With this structure, we might unit take a look at the implementation — the monitor has been referred to as with the fitting arguments, calling
confirm in case you’re utilizing Mockito.
Sadly, we fail to check our habits. We can’t assert that the monitoring came about when the consumer opened the display. Solely that the monitoring is accurately applied. That’s an enormous distinction! And to not point out it received’t scale properly. If by chance, somebody would delete this portion of code in your View, you’ll find yourself with:
- A regression because you received’t monitor anymore your open display.
- Some lifeless code in your ViewModel.
- Inexperienced unit assessments that cowl an unplugged use case.
Now that I’ve made my case, let’s see how we make our ViewModel lifecycle conscious.
Changing into lifecycle-aware allows you to observe any lifecycle occasions occurring to a selected View. Principally, you switch these occasions from the View to the ViewModel.
ViewModel already responds to lifecycle occasions by way of its
onCleared callback. The ViewModel’s lifecycle differs from the View but will get notified when it’ll now not be wanted.
To additional empower its lifecycle consciousness, we are able to depend on Google’s Jetpack library
androidx.lifecycle. If you need to make a element lifecycle-aware, merely implement its
LifecycleObserver interface and declare it as an observer from the lifecycle proprietor you’d like to watch. When you don’t have to react to all lifecycle occasions, you should use the
With this lifecycle-aware ViewModel, you now not have to override
onResume in your View. The ViewModel takes care of all enterprise logic. Congratulations!
However what about assessments? That’s why we’re doing this proper?
I’ve written an empty shell to check our ViewModel
To make this take a look at work, we want a mechanism transiting from one state to a different. We’ll want three issues:
LifecycleRegistryto control the lifecycle state.
LifecycleOwnerwe go to the
LifecycleObserver: the examined ViewModel for our use-case.
To create a
LifecycleRegistry, we are able to use the
createUnsafe technique particularly designed for assessments. We’ll inject the
LifecycleOwner to the
LifecycleRegistry as a mock:
val lifecycleOwner = mock<LifecycleOwner>()
val lifecycleRegistry = LifecycleRegistry.createUnsafe(lifecycleOwner)
Then we’ll have to register the ViewModel to the
Lastly, you may level to the specified lifecycle state:
lifecycleRegistry.currentState = Lifecycle.State.RESUMED
Right here is our examined class:
Now you can take a look at your ViewModel based mostly on particular lifecycle states! We might go a bit additional by eliminating a few of this boilerplate.
A technique can be to extract this into a category taking the lifecycle observer in its constructor.
In your examined class, create an occasion of it and alter the lifecycle standing with the offered public strategies.
Testing habits over implementation may also help you construct scalable apps. Whereas utilizing the MVVM structure, ensure that to extract all enterprise logic into your ViewModel.
By making your ViewModel lifecycle-aware, you delegate some logic belonging to the View to the ViewModel. Your View solely will get to replace its state and execute results coming from the ViewModel. Nothing extra!
Whereas this text focuses on ViewModels, nothing prevents you from making different elements lifecycle-aware. That might turn out to be useful in some use-cases when the enterprise holder element would wish to entry this info to carry out some motion with out having to show them to the View.
All the time preserve your view code to the minimal.