Android annotations Use the Dagger2 to decouple project dependencies

Source: Internet
Author: User

Objective:

Recently led the launch of the company's application refactoring work, how to make the project by refactoring to reduce the coupling, development efficiency, has been the direction of my efforts, today to learn a note framework Dagger2, and then see how to use it to reduce the coupling of the project.

Dagger2

Bottom line: A quick annotation framework for Android, Java, developed and maintained by Google, is a branch of Square's Dagger project.

Github:https://github.com/google/dagger

DAGGER2 relies on injection, dependency injection is an object-oriented programming pattern, it is to reduce the coupling, so-called coupling is the dependency between classes, so-called reduction of coupling is to reduce the class and class dependency relationship.

Dependent relationships

Java's object-oriented programming features, which typically refer to another Java object in one Java object, illustrate:

 Public class ClassA {    private  ClassB ClassB;      Public ClassA () {        =new  ClassB ();    }      Public  void dosomething () {        classb.dosomething ();    }}

As can be seen from the above example, ClassA need to use CLASSB to complete some specific operations, but we classa directly instantiate the CLASSB, so that the coupling produced, the first violation of the single principle of responsibility, CLASSB instantiation should be done by themselves, Should not be done by ClassA, the second violation of the opening and closing principle, once the classb of the constructor changes, you need to modify the ClassA constructor.

Reduce this coupling relationship through dependency injection:

1. How to pass parameters by constructing parameter

 Public class ClassA {    private  ClassB ClassB;      Public ClassA (ClassB ClassB) {        this. ClassB =ClassB;    }       Public  void dosomething () {        classb.dosomething ();    }}

2. By the Set method

 Public class ClassA {    private  ClassB ClassB;      Public ClassA () {    }    publicvoid  setclassb (ClassB ClassB) {          this. ClassB = ClassB;    }      Public  void dosomething () {        classb.dosomething ();    }}

3. How to inject through the interface

InterfaceClassbinterface {voidSetb (ClassB ClassB);} Public classClassAImplementsClassbinterface {PrivateClassB ClassB;  PublicClassA () {} @Override Public voidSetb (ClassB ClassB) { This. ClassB =ClassB; }     Public voiddosomething () {classb.dosomething (); }}

4. Through annotation injection

 Public class ClassA {    @Inject    ClassB ClassB;      Public ClassA () {    }    publicvoid  dosomething () {        classb.dosomething ();}    } 

Dagger2 uses the annotation injection method, and then compiles the way the object code is generated automatically to achieve the relationship between the host and the dependent person.

Dagger2 and simple instructions on how to use Android

The way to use Android is simple: Just add the configuration in the module's Build.gradle

Dependencies {  ' com.google.dagger:dagger:2.x '  com.google.dagger:dagger-compiler:2.x ' }

Dagger2 annotation Explanation

    • @Module-decorated classes are designed to provide dependency

    • The method of @Provides modification is used in the module class.

    • Where @Inject modification is required (can be a construction method, field, or general method)

    • @Component connect the @module and inject the bridge

Dagger2 Illustrative examples

Take the actual scenario cache management in the project as an example to try out the decoupling effect. The design follows a single responsibility principle.

1. First define cache classes and multitasking classes. and add @inject annotations on its constructor

Lcache class

/*** Created by Lichaojun on 2017/3/30. * Processing Cache*/ Public classLcache {Private Static  FinalString default_cache_name= "Lcache";//Default cache name    Private Static  Final  intdefault_max_cache_size=1024;//Default cache name    PrivateString Cachename=default_cache_name;//Cache Name    Private intMaxcachesize=default_max_cache_size;  PublicLcache () {} @Inject PublicLcache (String CacheName,intmaxcachesize) {         This. cachename=CacheName;  This. maxcachesize=maxcachesize; }     Public voidSavecache (string key, String value) {LOG.E (Lcachemanager.tag,"CacheName: =" +cachename); LOG.E (Lcachemanager.tag,"Maxcachesize: =" +maxcachesize); LOG.E (Lcachemanager.tag,"Savecache:key =" +key + "value =" +value); }     Public  voidReadcache (String key) {LOG.E (Lcachemanager.tag,"Readcache:key: =" +key); }}

Lexecutor class

 Public classLexecutor {Private Static Final intDefault_cpu_core = Runtime.getruntime (). Availableprocessors ();//The default thread pool maintains a minimum number of threads    Private intCoresize = Default_cpu_core;//The thread pool maintains a minimum number of threads@Inject PublicLexecutor (intcoresize) {         This. coresize =coresize; }     Public voidRunTask (Runnable Runnable) {if(runnable = =NULL) {            return; } log.e (Lcachemanager.tag,"Coresize: =" +coresize); LOG.E (Lcachemanager.tag,"RunTask");    Runnable.run (); }}
2. Use @module to define Lcachemodule, Lexecutormodule classes to provide related dependencies

Lcachemodule class

@Module  Public class lcachemodule {    /**     * Provides cached objects      @return  return cached objects      * /    @Provides    @Singleton    lcache providelcache () {        returnNew Lcache ("LCJ");    }}

Lexecutormodule class

@Module  Public class lexecutormodule {    /**     * Provides the minimum number     of maintenance threads for app multitasking @return  Returns the minimum number of maintenance threads     for multitasking *    /@Provides @Singleton    lexecutor providelexecutor () {         return New Lexecutor (ten);    }}
3. Use @component to associate @inject with @module and create a new Lcachecomponent class
@Component (modules = {Lcachemodule.  Class, Lexecutormodule. class }) @Singletonpublicinterface  lcachecomponent {    lcache lcache ();    // App Cache     lexecutor lexecutor ();   // app multi-task thread pool    void inject (Lcachemanager lcachemanager);}
4. Inject the object you want to rely on in the host
/**
* Created by Lichaojun on 2017/3/30.
* Cache Processing Management
*/
public class Lcachemanager {
public static final String tag=lcachemanager.class.getsimplename ();
Private Lcachecomponent cachecomponent;

private Static Class Singletonholder {
private static Lcachemanager instance = new Lcachemanager ();
}

Private Lcachemanager () {
Cachecomponent = Daggerlcachecomponent.builder (). Lcachemodule (New Lcachemodule ()). build ();
Cachecomponent.inject (this);
}

public static Lcachemanager getinstance () {
return singletonholder.instance;
}

public void Savecache (final string key, final string value) {
Cachecomponent.lexecutor (). RunTask (New Runnable () {
@Override
public void Run () {
Cachecomponent.lcache (). Savecache (Key,value);
}
});
}

public void Readcache (final String key) {
Cachecomponent.lexecutor (). RunTask (New Runnable () {
@Override
public void Run () {
Cachecomponent.lcache (). Readcache (key);
}
});
}
}
5. Using scene calls and simple explanations
Lcachemanager.getinstance (). Savecache ("Key", "Who is LCJ?");

Look at the print results:

Through the Dagger2 way at first may feel suddenly a simple thing, become complex, actually did not, through Dagger2 very good to handle the dependency, specific, such as our cache lcache need to add a maximum number of cache changes, if the previous way, We first need to modify the Lcache, such as modifying the constructor to add Maxcachesize, and then have to modify the Lcachemanager, now through the Dagger2 way, we only need to modify the lcachemodule on it, There is not much dependency between lcache instantiation and correlation parameters and Lcachemanager.

6. About @module offers a number of similar types of @provides

Based on the cache processing requirements above, we need to implement read/write using different multitasking lexecutor, and the minimum number of threads for Lexecutor is 5, we will add the Writelexecutor function in Lcachecomponent, as follows:

@Component (modules = {Lcachemodule.  Class, Lexecutormodule. class }) @Singletonpublicinterface  lcachecomponent {    lcache lcache ();    // App Cache     lexecutor lexecutor ();   // app multi-task thread pool     lexecutor writelexecutor ();   // App write cache multi-task thread pool    void inject (Lcachemanager lcachemanager);}

Add the Providewritelexecutor function that provides dependency initialization in Lexecutormodule. As follows:

@Module Public classLexecutormodule {/*** Minimum number of maintenance threads for app multitasking *@returnreturns the minimum number of maintenance threads for multiple tasks*/@Provides @Singleton lexecutor providelexecutor () {return NewLexecutor (10); }    /*** Minimum number of maintenance threads for app multitasking *@returnreturns the minimum number of maintenance threads for multiple tasks*/@Provides @Singleton lexecutor providewritelexecutor () {return NewLexecutor (5); }}

And then rebuild after writing the project, thought that everything is done, the results reported the following error,

What to do, is it Dagger2 so vulnerable, of course, not to solve the problem is very easy to use @named annotations to solve this problem, we only need to lcachecomponent writelexecutor () and

Add the same @named ("Writelexecutor") on Lexecutormodule's Providewritelexecutor () function.

The Provide function for the module is also a function that can pass parameters, but needs to provide the relevant parameters in the current module. For example: Lcachemodule can be modified as follows:

@Module Public classLcachemodule {/*** Provide cached objects *@returnReturning cached Objects*/@Provides @Singleton Lcache providelcache (@Named ("Lcache") String name, @Named ("Lcache")intmaxcachesize) {        return NewLcache (name,maxcachesize); }    /*** Provide cached objects *@returnReturning cached Objects*/@Provides @Singleton @Named ("Lcache") String Providelcachename () {return"Lcjcache"; }    /*** Provide cached objects *@returnReturning cached Objects*/@Provides @Singleton @Named ("Lcache")    intprovidelcachemaxsize () {return600; }}

The alias @name is also used here because in order to avoid the bound multiple times error caused the compilation failure, in the process of compiling Dagger2 automatically to find the relevant parameters for binding dependencies, this is quite magical.

Summarize:

Today, a simple example of the Dagger2 has a preliminary understanding and understanding, because the project has not adopted the MVP design model, is prepared to gradually adopt the DAGGER2+MVP to reduce the coupling in the project.

Android annotations Use the Dagger2 to decouple project dependencies

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.