0. Preface
Dagger2 is the first framework to implement full dependency injection using generated code, greatly reducing the user's coding burden,
This article mainly describes how to use Dagger2 for dependency injection. If you are not yet aware of dependency injection, see this article.
1. Simple Dependency Injection
First we build a simple Android app. We create a usermodel and then display it to TextView. The problem here is that when we created the Usermodel, we used the hard init described earlier. Once the creation of our Usermodel has changed (such as the need to pass into the context object to the constructor), we need to modify all the code that created the Usermodel. What we want to do is that the changes to Usermodel do not affect the code of the other modules (such as the mainactivity here).
1 2 3 4 5 6 7 8 9 10 11
|
PublicClassMainactivityExtends actionbaractivity {
@Override protected void onCreate(Bundle savedinstancestate) { super.oncreate (savedinstancestate); Setcontentview (R.layout.activity_main); Usermodel user = new Usermodel (); ((TextView) Findviewbyid (R.id.user_desc_line)). SetText (user.id + "\ n" + user.name + "\ n" + user.gender); } ... }
|
1.1 Build Dependencies
The first thing we think about is that the code that creates the Usermodel is independent, so that the mainactivity code is not modified. In Dagger2, the component responsible for providing dependencies is called module. The Activitymodule code we build is shown below.
1 2 3 4 5 6 7 |
@Module public class activitymodule { span class= "annotation" > @Provides usermodel provideusermodel () { return new usermodel (); } /span> |
As you can see, we use the @module identity type as module and provide a dependent method with the @provides identity.
1.2 Building INJECTOR
With components that provide dependencies, we also need to inject dependencies into the desired objects. The components that connect to provide dependencies and consume dependent objects are called injector. Dagger2, we call it component. The Activitycomponent code is as follows:
1 2 3 4
|
@Component (modules = Activitymodule.class) activitycomponent { Inject(mainactivity activity); }
|
As you can see, component is a Java interface that uses the @component identity. Interface's inject method requires a type object that consumes a dependency as a parameter.
Note: This must be the type mainactivity that really consumes the dependency, not the parent class, such as activity. Because Dagger2 generates dependency injection code at compile time, it looks for objects that can be injected into the parameter types of the inject method, but in fact these objects exist in mainactivity, not in activity. If the function declaration parameter is activity,dagger2, there is no object that needs to be injected. When you actually create an component instance for injection in mainactivity, the inject method that is generated by activity as a parameter is executed directly, causing all injections to fail. (yes, I fell into this hole.) )
1.3 Complete Dependency Injection
Finally, we need to build the Injector object in mainactivity to complete the injection. This part of the code is shown below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
PublicClassMainactivityExtendsactionbaractivity { Private Activitycomponent mactivitycomponent;
@Inject Usermodel Usermodel;
@Override void oncreate (Bundle savedinstancestate) { super.oncreate (savedinstancestate); Setcontentview (R.layout.activity_main); Mactivitycomponent = Daggeractivitycomponent.builder (). Activitymodule ( new activitymodule ()). build (); Mactivitycomponent.inject (this); } /span> |
First, we use the @inject flag to inject the object Usermodel (note that Usermodel cannot be private), The Activitycomponent interface class Daggeractivitycomponent created by Dagger2 is then generated to create component, calling its inject method to complete the injection.
At this point, we use dagger to achieve the simplest dependency injection.
2. Multilayer dependencies
In addition to the simplest form above, dagger2 can also use component as a component dependency to implement multi-layered dependency injection.
2.1 Build Dependencies
We are creating a new domain Model named Shoppingcartmodel. and follow the 1.1 method to build its module as follows.
1 2 3 4 5 6
|
@Module Containermodule { Providecartmodel() { New Shoppingcartmodel (); } }
|
2.2 Building Injector
Unlike 1.2, our injector provides a dependency not only from containermodule, we also need to use the Usermodel dependencies provided by the previous activitycomponent.
1 2 3 4
|
@Component (dependencies = activitycomponent.class, modules = Containermodule.class) containercomponent { Inject(mainactivity mainactivity); }
|
So as the code shows, we add activitycomponent to the dependencies parameter after component, making a component a dependency of another component.
2.3 Low-level component provide dependency
The current Activitycomponent code is shown below. You can see that it provides only the inject method, and does not provide the required usermodel dependency. What we need is to pass the Usermodel provided by Activitymodule to activitycomponent-dependent containercomponent.
The modified code is as follows:
1 2 3 4 5
|
@Component (modules = Activitymodule.class) activitycomponent { void inject (mainactivity activity); Usermodel(); }
|
As you can see, we add a method that provides Usermodel dependencies for the interface, and if you do not need to inject it directly, you can remove its inject method, at which point the component is only used as a dependent organizational module.
Finally, the code for Dependency injection in Mainactivity is as follows.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21st 22
|
PublicClassMainactivityExtendsactionbaractivity { Private Activitycomponent mactivitycomponent;
@Inject Usermodel Usermodel;
@Inject Shoppingcartmodel Cartmodel;
@Override ProtectedvoidOnCreate(Bundle savedinstancestate) { Super.oncreate (savedinstancestate); Setcontentview (R.layout.activity_main); Mactivitycomponent = Daggeractivitycomponent.builder (). Activitymodule (new Activitymodule ()). build (); Containercomponent containercomponent = Daggercontainercomponent.builder (). Activitycomponent (mActivityComponent). Containermodule (new Containermodule ()). build ();
Containercomponent.inject (this);
((TextView) Findviewbyid (R.id.user_desc_line)). SetText (usermodel.id + "\ n" + usermodel.name + "\ n" + Usermodel.gender + "\ n" + cartmodel.total); } ... }
|
3. Finally
This article attempts to use the simplest examples of how Android uses Dagger2 for dependency injection, so there are many dagger2 features that are not involved, such as @scope annotations, as well as parsing and debugging Dagger2 automatically generated code. For more in-depth analysis of the characteristics of dagger2, it is also necessary to make a summary after extensive use.
Reference
- Dagger 2
- Tasting Dagger 2 on Android
- Dependency injection with Dagger 2-the API
Using Dagger2 for Dependency injection (basic article)