* You can also go to GitHub to view this piece of paper
Brief introduction
When developing a program, various objects are used, and many objects need to be initialized before they can be used. For example, to manipulate a sharedpreference, you need to call Getsharedpreferences (String name,int mode) to get an object before you can use it. And if this object is used in multiple activity, you need to write the same code in every scene you use. This is not only troublesome, but also increases the likelihood of error. The purpose of dagger is that you do not need to initialize the object. in other words, any object that is declared can be used directly.
Principle
Dagger is the use of dependency injection , which uses annotation to mark objects that need to be injected, and to automatically inject all objects through the inject () method to automate the initialization process.
Example code:
public class Mainactivity extends Activity { //The object is tagged by @inject @Inject sharedpreferences sharedpreferences;< c2/> @Override protected void onCreate (Bundle savedinstancestate) { super.oncreate (savedinstancestate); Setcontentview (r.layout.activity_main); Injection-dependent objectgraph.create (appmodule.class). inject (this); Get the value of name and output System.out.println (sharedpreferences.getstring ("name", ""));} }
Dependency Injection (Dependency injection): An object (dependency) that uses a B in Class A requires an instance of new B or some other active way to get the object before it can be called. In the external way, the object of B is automatically assigned to a (injection) to achieve a relatively passive acquisition object, the process is called Dependency injection . Want to learn more about dependency injection you can Google yourself.
How to use
Take the example of a simple "boss and programmer" app. You want to implement the automatic injection of the Boss object, then first you have to tell the program how it initializes a boss. In Dagger, adding a @inject annotation to the Boss class's construction method, the program will find the tagged constructor and call it when needed to get a boss object.
public class Boss { ... @Inject public Boss () { ... } ...}
It is important to note that if the constructor contains parameters, dagger will fetch them first when constructing the object (otherwise, who is going to pass the argument?). , so you have to make sure that these parameters are constructed using @inject tags, or can be obtained by @provides annotations (described below).
Then, when declaring the Boss object, the same @inject annotation is added in front. The program automatically initializes the annotated object during dependency injection.
public class Mainactivity extends Activity { @Inject boss boss; ...}
Finally, the ObjectGraph class is created and the inject () method is executed and the current mainactivity is passed in as a parameter, and the Boss object is injected into the mainactivity.
public class Mainactivity extends Activity { @Inject boss boss; @Override protected void onCreate (Bundle savedinstancestate) { objectgraph.create (appmodule.class). inject (this); } ...}
So far, the process of injecting a boss object into the mainactivity using dagger is complete. There are two classes in this code: ObjectGraph and Appmodule. Where ObjectGraph is provided by the Dagger class, can be simply understood as a tool class, its create function parameters for all the module, this article is not detailed, if interested can follow me after the dagger detailed. Appmodule is a custom class with the following code:
@Module (injects = mainactivity.class) public class Appmodule {}
As you can see, Appmodule is an empty class with only one line of annotations. @Module Note that this class is a module,module function is to provide information and let objectgraph know how to inject all the dependencies. For example, the above code declares the information that can be injected into an object: Mainactivity.class (using explicit declarations such a cumbersome, superfluous way is related to the principle of dagger, this article does not detail).
Custom dependencies
Annotating the construction method is a good way to implement dependencies, but it does not apply to all situations.
- Interface (Interface) is not a constructor method.
- Classes provided by third-party libraries, whose construction methods cannot be annotated
- Some classes require flexible selection of the initialized configuration, rather than a single construction method
For such cases, you can use @provides annotations to provide a dedicated initialization method that implements a custom dependency.
@ProvidesCoder Providecoder (Boss boss) { return new coder (boss);}
Similarly, if the method of @Provides annotation contains parameters, all its parameters are guaranteed to be obtained by Dagger.
All methods with @provides annotations need to be encapsulated in a class with @module annotations:
@Modulepublic class Appmodule { @Provides coder Providecoder (boss boss) { return new coder (boss);} }
Single case
Dagger supports a single case, and the implementation is simple:
Single-instance mode with @Inject annotation construction method @singletonpublic class Boss { ... @Inject public Boss () { ... } ...}
The java//@Provides Annotation provides a singleton mode of initialization method @provides@singletoncoder Providecoder (Boss boss) { return new coder (boss);}
After adding the @singleton annotation in the above method, the object will only be initialized once, and then each time it will be injected directly into the same object.
Qualifier (qualifier)
If there are two types of programmers whose power values are 5 and 1000, how should the dagger make a distinction between them? Using @qualifier annotations
First, create a @interface:
@Qualifier @documented@retention (RUNTIME) public @interface level { String value () Default "";}
Then, set the @provides method separately for these two types of programmers, and use @qualifier to make different tags for them:
@Provides @Level ("Low") coder Providelowlevelcoder () { coder coder = new Coder (); Coder.setname ("War five Slag"); Coder.setpower (5); return coder;} @Provides @Level ("High") coder Providehighlevelcoder () { coder coder = new Coder (); Coder.setname ("The Great God"); Coder.setpower (+); return coder;}
Finally, the corresponding @qualifier annotations are used as well.
@Inject @Level ("Low") coder Lowlevelcoder, @Inject @Level ("High") coder Highlevelcoder;
Compile-time check
Essentially, dagger will check the code at compile time and report a compile error when the check fails (why?). This is related to the principle of dagger, interested in the words can be concerned about my post dagger detailed). There are three main things to check:
- All classes that contain dependency injection need to be explicitly declared in the appropriate module.
- The parameters of all @provides methods in a module must provide the appropriate @provides method in this module, or add "complete = false" after the @module annotation Note that this is an incomplete module (that is, it will be extended by other module).
- All @provides methods in a module are used by the injected object it declares, or after the @module annotation, add "library = Ture" (that is, it exists to extend the other module).
If you need to know more about dagger, you can refer to the official documentation, or follow my detailed article.
In addition, our company neighbor Community recruitment android Development, address Beijing Haidian Bamboo Bridge.
My github Address: Https://github.com/rengwuxian