Scoping object A to object B means that object B always holds the same instance of A throughout its lifetime. When it comes to DI (dependency injection), scoping object A to a container means that the container always provides the same instance of A until it is destroyed.
In Hilt, you can scope types to certain containers or components via annotations. For example, your application has a UserManager type that handles logging in and out. You can scope that type to the ApplicationComponent (the ApplicationComponent is a container that is managed by the lifecycle of the entire application) using the @Singleton annotation. Scoped types are passed down the component hierarchy in the application component: In this case, the same UserManager instance will be provided to the rest of the Hilt components in the hierarchy. Any type in your application that depends on the UserManager will get the same instance.
Note: By default, bindings in Hilt are unscoped. They do not belong to any component and are accessible throughout your project. A different instance of the type is provided each time it is requested. When you scope a binding to a component, it limits where you can use the binding and what dependencies the type can have. In Android, you can manually scope without using a DI library using the Android Framework. Let's look at how to do manual scoping and how to use Hilt instead. Finally, we'll compare manual scoping with the Android Framework and scoping with Hilt. Scoping in Android After reading the above definition, you may have such an objection: using an instance variable of a type in a specific class can also limit the scope of the variable type. That's right! Without using DI, you can do the following:
The analyticsAdapter variable is scoped to the lifecycle of MyActivity, which means that as long as the Activity is not destroyed, the variable will be the same instance. If another class needs to access this scoped variable for some reason, it will get the same instance every time it accesses it. When a new MyActivity instance is created (such as when a system setting changes), a new AnalyticsAdapter instance will be created. Using Hilt, the equivalent code is as follows:
Each creation of MyActivity will hold a new instance of the ActivityComponent DI container, which will provide the same AnalyticsAdapter instance to dependencies down the component hierarchy until the Activity is destroyed.
Scoping via ViewModel However, we may want our AnalyticsAdapter to persist after system settings change! Or, we may want to keep the instance scoped to the Activity until the user leaves the Activity. To do this, you can use a ViewModel from the component architecture because it can persist after system settings change.
Without dependency injection, you might have code like this:
In this way, you scope the AnalyticsAdapter to the ViewModel. Because the Activity has access to the ViewModel, you can always get the same AnalyticsAdapter instance in the Activity. Using Hilt, you can achieve the same behavior by scoping the AnalyticsAdapter to the ActivityRetainedComponent, since the ActivityRetainedComponent can also be persisted across system setting changes.
If you want to keep the ViewModel for view logic while following good DI practices, you can use @ViewModelInject to provide the ViewModel's dependencies, which is described in detail in: Documentation | Injecting ViewModel objects with Hilt. This way, the AnalyticsAdapter does not need to be scoped to the ActivityRetainedComponent, because it is now manually scoped to the ViewModel:
What we have just seen can be applied to any Hilt component managed by the Android Framework lifecycle classes. Click to view all available scopes. Going back to our original example, limiting the scope to ApplicationComponent is equivalent to holding the instance in the Application class when not using a DI framework.
Comparison of Hilt and ViewModel scope The advantage of using Hilt scopes is that you can use the scoped types in the Hilt component hierarchy; with ViewModel, you must manually access the scoped types through the ViewModel. The advantage of using ViewModel scoping is that you can hold the ViewModel in any LifecyclerOwner object in your application. For example, if you use the Jetpack Navigation library, you can bind the ViewModel to the NavGraph.
Hilt provides a limited number of scopes. There may not be a scope that fits your specific use case. For example, nested fragments, for this case, you can fall back to using ViewModel to limit the scope. Using Hilt to inject ViewModel As mentioned above, you can use @ViewModelInject to inject dependencies into your ViewModel. The reason for this is that these bindings are stored in the ActivityRetainedComponent, which is why you can only inject unscoped types, or types scoped to ActivityRetainedComponent and ApplicationComponent. If the Activity or Fragment is modified by the @AndroidEntryPoint annotation, you can get the ViewModel factory generated by Hilt through the getDefaultViewModelProviderFactory() method. Since you can use these ViewModel factories in ViewModelProvider, the way you get ViewModel becomes more flexible. For example: limit the scope to the ViewModel of BackStackEntry. Scoping has some cost, because the provided object will remain in memory until the holder is destroyed. Carefully consider using scoped objects in your application. Scoping is appropriate if the object's internal state requires the use of the same instance, the object needs to be synchronized, or the object is expensive to create. Of course, when you need to limit the scope, you can use the scope annotations in Hilt or use the Android Framework directly. |
<<: Package visibility in Android 11
>>: Is the 5G replacement trend over? You may have misunderstood!
From Haidilao to Daancha, Douyin has demonstrated...
[[130837]] The low-coding mobile development tool...
On July 15, 2020, the Ministry of Industry and In...
This article reviews and compares two similar ope...
Author: Fang Baomin, Chief Physician, Beijing Hos...
This article has 6,129 words and discusses in det...
Today, there was news online that "WeChat ha...
【51CTO.com original article】 [51CTO original arti...
Have you ever had this experience , your boss cal...
January 12, Apple has achieved great success in 2...
Course Contents: 1. "Combo 3.0" Lecture...
The reporter learned from the FAST Operation and ...
According to foreign media reports, despite Apple...
iPhone 6 and iPhone 6 Plus will soon be launched ...
Author | Feng Ziyang Review | Dong Chenhui Editor...