美文网首页学习收藏Android收藏集
王学岗 Dagger2的使用从简单到复杂

王学岗 Dagger2的使用从简单到复杂

作者: 王学岗 | 来源:发表于2018-10-20 16:25 被阅读351次

    第一部分

    dagger2是一个依赖注入的框架,举个例子如果我们不适用dagger注入,我们调用一个对象必须使用构造方法,这样就会造成了类与类的组合,但dagger的使用解决了这一问题。
    这是dagger的官网

    我们看一下跟dagger相关的概念,
    @Inject
    通常在需要依赖的地方使用这个注解。换句话说,你用它告诉Dagger这个类或者字段需要依赖注入。这样,Dagger就会构造一个这个类的实例并满足他们的依赖。 官方点说就是带有此注解的属性或构造方法将参与到依赖注入中,Dagger2会实例化有此注解的类。
    @Module
    Modules类里面的方法专门用来提供依赖,他就像一个工厂一样去生产需要添加依赖的实例。所以我们定义一个类,用@Module来注解,这样Dagger在构造类的实例的时候,就知道从哪里去找到需要的依赖。modules的一个重要特性是它们设计为分区并组合在一起(例如,我们的app中可以有多个组成在一起的modules)。它里面定义一些用@Provides注解的以provide开头的方法,这些方法就是所提供的依赖,Dagger2会在该类中寻找实例化某个类所需要的依赖。
    @Provides
    上面引入了这个概念了。在modules中,我们定义的方法是用@Provides这个注解,以此来告诉Dagger我们想要构造对象并提供这些依赖。
    @Component
    Components从根本上来说他就是一个注入器,也可以说是用来将@Inject和@Module联系起来的桥梁,它的主要作用就是连接这两个部分。Components可以提供所有定义了的类型的实例(inject需要),比如:我们必须用@Component注解一个接口然后列出所有的 。功能是从@Module中获取依赖并将依赖注入给@Inject

    dagger必不可少的三个元素:Module,Component,Container
    这里有张图来说明它们之间的关系。


    dagger2222222222.png

    第二部分 Dagger2的基本使用(上)

    下面我们看下具体怎么使用
    首先要导入依赖

    dependencies {
        implementation 'com.google.dagger:dagger:2.16'
        annotationProcessor 'com.google.dagger:dagger-compiler:2.16'}
    
    

    这里有个ApiService的类,我们需要在MainActivity中使用它的实例,如果我们不用dagger,我们就只能new ApiService(),但是我们现在使用dagger,就不需要new了。

    先看下ApiService这个没用的类

    package com.example.dagger2test;
    
    import android.util.Log;
    public class ApiService {
        public void register() {
            Log.i("zhang_xin","register成功");
        }
    }
    
    

    等下我们要使用dagger获取它的实例。

    package com.example.dagger2test;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    
    import javax.inject.Inject;
    
    public class MainActivity extends AppCompatActivity {
        @Inject     
        ApiService   mApiService;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
           
        }
    }
    

    在MainActivity里我们使用@inject注解,告诉dagger,我需要ApiService的实例。dagger就会从@Component注释的接口中寻找ApiService的实例,那好,我们下面创建这个接口。

    package com.example.dagger2test;
    
    import dagger.Component;
    
    @Component(modules = {?.class})//关联到module
    public interface UserComponet {
     
    }
    

    大家看下Component的源码

    public @interface Component {
      /**
       * A list of classes annotated with {@link Module} whose bindings are used to generate the
       * component implementation. Note that through the use of {@link Module#includes} the full set of
       * modules used to implement the component may include more modules that just those listed here.
       */
      Class<?>[] modules() default {};
    
      /**
       * A list of types that are to be used as <a href="#component-dependencies">component
       * dependencies</a>.
       */
      Class<?>[] dependencies() default {};
    

    可以发现,Component需要module,我们需要在?处传入我们的module
    下面我们创建module

    package com.example.dagger2test;
    
    import dagger.Module;
    import dagger.Provides;
     
    public class UseModule {
        @Provides//提供依赖
        public ApiService provideApiService(){
            return new ApiService();
        }
    }
    
    

    在module里我们真正创建ApiService的实例,这个提供ApiService实例的方法,我们需要标注为@provides
    我们现在重新捋一下我们的思路
    在MainActivity(就是图中Container)中,我们需要ApiService的实例,我们在ApiService上加上@inject注解,这样dagger就知道我们需要ApiService的实例,dagger就会去@Component注解下的类去找该实例,commponent是一个桥梁,它关联了很多modules。我们看下@Component的代码

    package com.example.dagger2test;
    
    import dagger.Component;
    
    @Component(modules = {UseModule.class}) 
    public interface UserComponet {
        
    }
    
    

    注意,以上只是Module与Component进行了关联,我说过Component是一个桥梁,所我们还需要把Component与MainActivity进行关联,

    package com.example.dagger2test;
    
    import dagger.Component;
    
    @Component(modules = {UseModule.class})//关联到module
    public interface UserComponet {
        void inject(MainActivity activity);//关联到Activity
    }
    
    

    从这行注释@Component(modules = {UseModule.class}) ,dagger就知道要去UseModule里获取ApiService的实例。
    我们在看下UseModele类,在这个类里获取ApiService的实例,注意,该类需要添加@module注解。提供对象的方法添加@Prividers,方法的返回值为ApiService且有@Provides注释,那么dagger就会从这个方法里获取ApiService对象

    package com.example.dagger2test;
    
    import dagger.Module;
    import dagger.Provides;
    @Module
    public class UseModule {
        @Provides//提供依赖
        public ApiService provideApiService(){
            return new ApiService();
        }
    }
    
    

    到这里我们在MainActivity(Container)里调用ApiService实例的代码就全部完成了。然后我们rebuild我们的工程
    这个时候dagger会自动生成DaggerUserComponet类,该类有个create(),会生成UserComponet的实例,然后通过该实例我们调用UserComponet的inject方法。完整代码如下

    package com.example.dagger2test;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    
    import javax.inject.Inject;
    
    /**
     * 依赖注入框架,解决繁琐的依赖关系
     * 必不可少的三种元素:Module,Component,Container,module提供依赖的集合,里面有很多方法是提供依赖的
     * ,component
     */
    public class MainActivity extends AppCompatActivity {
        @Inject//dagger会从commponent里去找ApiService的实例。使用依赖
        ApiService mApiService;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    //生成UserComponet的实例,调用inject()
            DaggerUserComponet.create().inject(this);
            mApiService.register();
        }
    }
    
    

    运行会输出
    10-20 15:22:10.585 22065-22065/com.example.dagger2test I/zhang_xin: register成功
    为了方便大家看,我把所有相关的类在贴一遍。

    package com.example.dagger2test;
    
    import android.util.Log;
    public class ApiService {
        public void register() {
            Log.i("zhang_xin","register成功");
        }
    }
    
    
    package com.example.dagger2test;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    
    import javax.inject.Inject;
    
    public class MainActivity extends AppCompatActivity {
        @Inject//dagger会从commponent里去找ApiService的实例。使用依赖
        ApiService mApiService;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            DaggerUserComponet.create().inject(this);
            mApiService.register();
        }
    }
    
    package com.example.dagger2test;
    
    import dagger.Component;
    
    @Component(modules = {UseModule.class})//关联到module
    public interface UserComponet {
        void inject(MainActivity activity);//关联到Activity
    }
    
    
    package com.example.dagger2test;
    
    import dagger.Module;
    import dagger.Provides;
    @Module
    public class UseModule {
        @Provides//提供依赖
        public ApiService provideApiService(){
            return new ApiService();
        }
    }
    
    

    第三部分 Dagger2的基本使用(下)

    我们再来看一下复杂的例子。
    我们需要MainActivity类里获取UserManager实例,UserManager的构造方法需要传入另外两个类的实例。我们看下UserManager类

    package com.example.dagger2test;
    
    public class UserManager {
        private ApiService apiService;
        private UserStore userStore;
    
        public UserManager(ApiService apiService, UserStore userStore) {
            this.apiService = apiService;
            this.userStore = userStore;
        }
        public void register(){
            apiService.register();
            userStore.register();
        }
    }
    
    

    这是UserStore类

    package com.example.dagger2test;
    
    import android.util.Log;
    
    public class UserStore {
        public void register(){
            Log.i("zhang_xin","UserStore注册成功");
        }
    }
    
    

    我们有两种方法
    第一种,修改UseModule文件

    package com.example.dagger2test;
    
    import dagger.Module;
    import dagger.Provides;
    
    @Module
    public class UseModule {
        @Provides
        public ApiService getApiService() {
            return new ApiService();
        }
    
        @Provides
        public UserStore getUserStore() {
            return new UserStore();
        }
    
        @Provides
        public UserManager getUserManager(ApiService apiService, UserStore userStore) {
            return new UserManager(apiService, userStore);
        }
    }
    
    

    然后在MainActivity中调用用

    package com.example.dagger2test;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    
    import javax.inject.Inject;
    
    public class MainActivity extends AppCompatActivity {
        @Inject
        UserManager userManager;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            DaggerUserComponet.create().inject(this);
            userManager.register();
        }
    }
    
    

    看下打印输出结果
    10-20 17:03:03.092 27717-27717/com.example.dagger2test I/zhang_xin: ApiService register成功 UserStore注册成功
    第二种方法,使用构造方法。
    我们先把UseModule中方法注释掉

    package com.example.dagger2test;
    
    import dagger.Module;
    import dagger.Provides;
    
    @Module
    public class UseModule {
    //    @Provides
    //    public ApiService getApiService() {
    //        return new ApiService();
    //    }
    //
    //    @Provides
    //    public UserStore getUserStore() {
    //        return new UserStore();
    //    }
    
        @Provides
        public UserManager getUserManager(ApiService apiService, UserStore userStore) {
            return new UserManager(apiService, userStore);
        }
    }
    
    

    然后修改ApiService和UseModule两个类,添加@Inject注释的方法。

    package com.example.dagger2test;
    
    import android.util.Log;
    
    import javax.inject.Inject;
    
    public class UserStore {
        @Inject
        public UserStore(){
    
        }
        public void register(){
            Log.i("zhang_xin","UserStore注册成功");
        }
    }
    
    
    package com.example.dagger2test;
    
    import android.util.Log;
    
    import javax.inject.Inject;
    
    public class ApiService {
        @Inject
        public ApiService() {
        }
    
        public void register() {
            Log.i("zhang_xin", "ApiService register成功");
        }
    }
    
    

    运行MainActivity
    10-20 17:14:14.795 28228-28228/com.example.dagger2test I/zhang_xin: ApiService register成功 UserStore注册成功
    由以上两种方法我们可以得出结论。
    如果Module中没有提供@Providers注释的方法,Dagger会去调用@Inject注释的方法。

    第四部分

    我们现在有这么个需求,那就是UseModule的构造方法需要传入参数。我们修改下UseModule类

    package com.example.dagger2test;
    
    import android.content.Context;
    
    import dagger.Module;
    import dagger.Provides;
    
    @Module
    public class UseModule {
        private Context context;
        public UseModule (Context context){
            this.context=context;
        }
        @Provides
        public ApiService getApiService() {
            return new ApiService();
        }
    
        @Provides
        public UserStore getUserStore() {
            return new UserStore(this.context);
        }
    
        @Provides
        public UserManager getUserManager(ApiService apiService, UserStore userStore) {
            return new UserManager(apiService, userStore);
        }
    }
    
    

    现在大家看下,我们怎么在MainActivity类里调用
    DaggerUserComponet.create().inject(this);肯定是行不通了

    package com.example.dagger2test;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    
    import javax.inject.Inject;
    
    public class MainActivity extends AppCompatActivity {
        @Inject
        UserManager userManager;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            DaggerUserComponet.builder().useModule(new UseModule(this)).build().inject(this);
            userManager.register();
        }
    }
    
    

    第五部分

    假设我们现在有这么一个需求,ApiService里需要传入一个参数(实际开发中可能是OkHttpClient等,我们这里只简单的使用Dog),我们可以这么做
    ,先看下Dog类

    package com.example.dagger2test;
    
    public class Dog {
    }
    
    

    看下UserManager类

    package com.example.dagger2test;
    
    public class UserManager {
        private ApiService apiService;
        private UserStore userStore;
    
        public UserManager(ApiService apiService, UserStore userStore) {
            this.apiService = apiService;
            this.userStore = userStore;
        }
    
        public void register(){
            apiService.register();
            userStore.register();
        }
    }
    
    

    看下ApiService类

    package com.example.dagger2test;
    
    import android.util.Log;
    
    public class ApiService {
       private Dog dog;
    //注意 dog是单例对象
        public ApiService(Dog dog) {
            this.dog = dog;
        }
    
        public void register() {
            Log.i("zhang_xin", "ApiService register成功");
        }
    }
    
    

    我们可以单独写一个针对Dog类的DogModule

    package com.example.dagger2test;
    
    import javax.inject.Singleton;
    
    import dagger.Module;
    import dagger.Provides;
    
    @Module
    public class DogModule {
        @Singleton//增加单例注释
        @Provides
        public Dog getUser(){
            return new Dog();
        }
    }
    
    

    然后在UseModule中引用DogMoudle

    package com.example.dagger2test;
    
    import android.util.Log;
    
    import javax.inject.Singleton;
    
    import dagger.Module;
    import dagger.Provides;
    //includes引入另外一个module
    @Module(includes = {DogModule.class})
    public class UseModule {
        @Provides
        public ApiService getApiService(Dog dog) {
            Log.i("zhang_xin", "dog是否是单例:" + dog.toString());
            return new ApiService(dog);
        }
    
        @Provides
        public UserStore getUserStore() {
            return new UserStore();
        }
    
        @Provides
        public UserManager getUserManager(ApiService apiService, UserStore userStore) {
            return new UserManager(apiService, userStore);
        }
    }
    
    

    同时UserComponet也需要修改

    package com.example.dagger2test;
    
    import javax.inject.Singleton;
    
    import dagger.Component;
    //增加单例注释
    @Singleton
    @Component(modules = {UseModule.class})//关联到module
    public interface UserComponet {
        void inject(MainActivity activity);//关联到Activity
    }
    
    

    下面我们在MainActivity中调用

    package com.example.dagger2test;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    
    import javax.inject.Inject;
    
    public class MainActivity extends AppCompatActivity {
        @Inject
        UserManager userManager;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
          DaggerUserComponet.builder().useModule(new UseModule()).dogModule(new DogModule()).build().inject(this);
            userManager.register();
        }
    }
    
    

    最后我们看一下打印输出
    10-20 20:23:15.805 31622-31622/com.example.dagger2test I/zhang_xin: dog是否是单例:com.example.dagger2test.Dog@b45757d 10-20 20:23:15.809 31622-31622/com.example.dagger2test I/zhang_xin: ApiService register成功 UserStore注册成功
    多次打印都是这个值:com.example.dagger2test.Dog@b45757d;
    说明Dog确实是单例模式

    除此之外还有一种方法,我们首先把UseModule恢复原来的样子

    package com.example.dagger2test;
    
    import android.util.Log;
    
    import javax.inject.Singleton;
    
    import dagger.Module;
    import dagger.Provides;
    //这里删除includes
    @Module
    public class UseModule {
        @Provides
        public ApiService getApiService(Dog dog) {
            Log.i("zhang_xin", "dog是否是单例:" + dog.toString());
            return new ApiService(dog);
        }
    
        @Provides
        public UserStore getUserStore() {
            return new UserStore();
        }
    
        @Provides
        public UserManager getUserManager(ApiService apiService, UserStore userStore) {
            return new UserManager(apiService, userStore);
        }
    }
    
    

    然后修改我们的UserComponet类

    package com.example.dagger2test;
    
    import javax.inject.Singleton;
    
    import dagger.Component;
    @Singleton
    //增加DogModule.class
    @Component(modules = {UseModule.class,DogModule.class})//关联到module
    public interface UserComponet {
        void inject(MainActivity activity);//关联到Activity
    }
    
    

    其余的代码不变,效果一样

    第六部分 创建和区分不同实例(上)

    我们现在有新的需求了,我们在MainActivity里需要两个ApiService对象,该怎么操作呢?其实也很简单,只需要在UseModule中提供两个@Provides注释的方法,同时在MainActivity和UseModule中添加@Named注释,注意MainActivity中的@Named和UseModule中的@Named字段要一一对应。看下代码更一目了然
    ApiService类

    package com.example.dagger2test;
    
    import android.util.Log;
    
    public class ApiService {
    
        public void register() {
            Log.i("zhang_xin", "ApiService register成功");
            Log.i("zhang_xin",this.toString());
        }
    }
    
    

    MainActivity需要两个ApiService类,每个对象前添加@Named注释

    package com.example.dagger2test;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    
    import javax.inject.Inject;
    import javax.inject.Named;
    
    public class MainActivity extends AppCompatActivity {
        @Named("1")
        @Inject
        ApiService apiService1;
        @Inject
        @Named("2")
        ApiService apiService2;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            DaggerUserComponet.builder().useModule(new UseModule()).build().inject(this);
            apiService1.register();
            apiService2.register();
        }
    }
    
    

    UseNodule类,添加@Named注释与MainActivity一一对应

    package com.example.dagger2test;
    
    import javax.inject.Named;
    
    import dagger.Module;
    import dagger.Provides;
    
    @Module
    public class UseModule {
        @Provides
        @Named("1")
        public ApiService getApiService1(Dog dog) {
            return new ApiService();
        }
        @Provides
        @Named("2")
        public ApiService getApiService2(Dog dog) {
            return new ApiService();
        }
    }
    
    

    看下打印输出
    10-22 19:44:09.799 31505-31505/com.example.dagger2test I/zhang_xin: ApiService register成功 com.example.dagger2test.ApiService@b45757d 10-22 19:44:09.800 31505-31505/com.example.dagger2test I/zhang_xin: ApiService register成功 com.example.dagger2test.ApiService@20d4c72
    可以看出两个ApiService的内存地址不一样,是两个不同的对象。
    注意,如果我们不添加@Named注释,dagger会根据返回值类型进行匹配。

    第七部分 dagger创建和区分不同实例(下)

    上接第六部分,第六部分的功能我们还可以这样实现,自定义@Interface
    我们首先自定义两个@Interface文件,一个叫@First,一个叫@Second

    package com.example.dagger2test;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.Retention;
    
    import javax.inject.Qualifier;
    
    import static java.lang.annotation.RetentionPolicy.RUNTIME;
    
    @Qualifier
    @Documented
    @Retention(RUNTIME)
    public @interface First {
    }
    
    package com.example.dagger2test;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.Retention;
    
    import javax.inject.Qualifier;
    
    import static java.lang.annotation.RetentionPolicy.RUNTIME;
    
    @Qualifier
    @Documented
    @Retention(RUNTIME)
    public @interface Second {
    }
    
    

    在UseModule和MainActivity中,我们需要把@Named注释分别改为@First和@Second,我们看下代码

    package com.example.dagger2test;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    
    import javax.inject.Inject;
    import javax.inject.Named;
    
    public class MainActivity extends AppCompatActivity {
        @First
        @Inject
        ApiService apiService1;
        @Second
        @Inject
        ApiService apiService2;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            DaggerUserComponet.builder().useModule(new UseModule()).build().inject(this);
            apiService1.register();
            apiService2.register();
        }
    }
    
    
    package com.example.dagger2test;
    
    import dagger.Module;
    import dagger.Provides;
    
    @Module
    public class UseModule {
        @Provides
        @First
        public ApiService getApiService1() {
            return new ApiService();
        }
        @Provides
        @Second
        public ApiService getApiService2() {
            return new ApiService();
        }
    }
    
    

    看下运行效果
    10-22 19:59:50.668 32434-32434/com.example.dagger2test I/zhang_xin: ApiService register成功 com.example.dagger2test.ApiService@b45757d ApiService register成功 10-22 19:59:50.669 32434-32434/com.example.dagger2test I/zhang_xin: com.example.dagger2test.ApiService@20d4c72

    第八部分:Singleton 单例讲解(上)

    我们需要ApiService是单例模式
    首先我们看下ApiService类

    package com.example.dagger2test;
    
    import android.util.Log;
    
    public class ApiService {
    
        public void register() {
            Log.i("zhang_xin", "ApiService register成功");
            Log.i("zhang_xin",this.toString());
        }
    }
    
    

    这个时候我们需要在Module类的方法中添加@Singleton注释,代码如下

    package com.example.dagger2test;
    
    import javax.inject.Singleton;
    
    import dagger.Module;
    import dagger.Provides;
    
    @Module
    public class UseModule {
        @Singleton
        @Provides
        public ApiService getApiService() {
            return new ApiService();
        }
    }
    
    

    注意我们现在需要修改UserComponent类,他的类也需要添加@Singleton注释

    package com.example.dagger2test;
    
    import javax.inject.Singleton;
    
    import dagger.Component;
    @Singleton//因为UseModule添加了该注释,所以这里也需要添加注释
    @Component(modules = {UseModule.class,DogModule.class})//关联到module
    public interface UserComponet {
        void inject(MainActivity activity);//关联到Activity
    }
    
    

    然后我们看下MainActivity

     package com.example.dagger2test;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    
    import javax.inject.Inject;
    import javax.inject.Named;
    
    public class MainActivity extends AppCompatActivity {
        @Inject
        ApiService apiService1;
        @Inject
        ApiService apiService2;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            DaggerUserComponet.builder().useModule(new UseModule()).build().inject(this);
            apiService1.register();
            apiService2.register();
    
        }
    }
    
    

    我们多次运行都会打印这个结果
    10-22 20:33:15.896 3145-3145/com.example.dagger2test I/zhang_xin: ApiService register成功 com.example.dagger2test.ApiService@b45757d ApiService register成功 com.example.dagger2test.ApiService@b45757d
    apiService1和apiService2内存地址一样,说明它们是同一个对象。

    第八部分:Singleton 单例讲解(下)

    我们第七部分实现了单例模式,但是这种方法实现的单例模式是有问题的,如果我们现在在创建一个MainActivity2和与之相关的@Component注释的类,那么这个时候我们无法保证两个Activity中的ApiService是同一个。其实大家翻翻Dagger的源码就会发现,Dagger的单例模式必须要保证是同一个@Component注释的类。
    我们先看这样的一个例子,我们把访问网络的类CallNets设置为单例模式
    这个是ApiService类,他里面有一个CallNets类,这个类是单例模式。

    package com.example.daggertest2;
    
    import android.util.Log;
    
    public class ApiService {
        private CallNets callNets;
    
        public ApiService(CallNets callNets) {
            this.callNets = callNets;
        }
    
        public void register() {
            Log.i("zhang_xin", "apiService注册成功");
        }
    }
    
    

    CallNets类,实际开发中可能是OkhttpClient等。

    package com.example.daggertest2;
    
    public class CallNets {
    //访问网络的逻辑
    }
    
    

    CallNetsModule类,方法我们注解成单例模式

    package com.example.daggertest2;
    
    import android.util.Log;
    
    import javax.inject.Singleton;
    
    import dagger.Module;
    import dagger.Provides;
    
    @Module
    public class CallNetsModule {
        @Singleton
        @Provides
        public CallNets getCallNets(){
            CallNets callNets=new CallNets();
            Log.i("zhang_xin",callNets.toString());
            return callNets;
        }
    
    }
    
    

    接下来我们创建了两个@Component注解的类

    package com.example.daggertest2;
    
    import javax.inject.Singleton;
    
    import dagger.Component;
    @Singleton
    @Component(modules=UserModule.class)
    public interface LoginComponet {
        void inject(LoginActivity activity);
    }
    
    
    package com.example.daggertest2;
    
    import javax.inject.Singleton;
    
    import dagger.Component;
    @Singleton
    @Component(modules = UserModule.class)
    public interface UserComponet {
        void inject(MainActivity activity);
    }
    
    

    UserModule和UserManager

    package com.example.daggertest2;
    
    public class UserManager {
        private ApiService apiService;
        public UserManager(ApiService apiService){
            this.apiService=apiService;
        }
        public void register(){
            apiService.register();
        }
    }
    
    
    package com.example.daggertest2;
    
    import dagger.Module;
    import dagger.Provides;
    
    @Module(includes = {CallNetsModule.class})
    public class UserModule {
    
        @Provides
        public ApiService getApiService(CallNets callNets){
            return new ApiService(callNets);
        }
        @Provides
        public UserManager getUserManager(ApiService apiService){
            return new UserManager(apiService);
        }
    }
    
    

    两个Activity

    package com.example.daggertest2;
    
    import android.content.Intent;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    
    import javax.inject.Inject;
    
    public class MainActivity extends AppCompatActivity {
        @Inject
        UserManager userManager;
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            DaggerUserComponet.builder().userModule(new UserModule()).callNetsModule(new CallNetsModule()).build().inject(this);
            userManager.register();
            startActivity(new Intent(this,LoginActivity.class));
        }
    }
    
    
    package com.example.daggertest2;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    
    import javax.inject.Inject;
    
    public class LoginActivity extends AppCompatActivity {
       @Inject
        UserManager userManager;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_login);
            DaggerLoginComponet.builder().userModule(new UserModule()).callNetsModule(new CallNetsModule()).build().inject(this);
            userManager.register();
        }
    }
    
    

    我们看下打印输出
    /zhang_xin: com.example.daggertest2.CallNets@b45757d /zhang_xin: apiService注册成功 /zhang_xin: com.example.daggertest2.CallNets@eea8d0f /zhang_xin: apiService注册成功
    很明显,两个CallNets不是同一个对象,我们虽然标注了@Singleton,但因为创建了两个Componet,所以得到的是两个不同的CallNets对象。
    接下来我们就解决这个问题。
    我们需要创建一个最高级别的Component
    首先我们把CallNetsModule中无法提供单例的方法注释掉

    package com.example.daggertest2;
    
    import android.util.Log;
    
    import javax.inject.Singleton;
    
    import dagger.Module;
    import dagger.Provides;
    
    @Module
    public class CallNetsModule {
    //    @Singleton
    //    @Provides
    //    public CallNets getCallNets(){
    //        CallNets callNets=new CallNets();
    //        Log.i("zhang_xin",callNets.toString());
    //        return callNets;
    //    }
    
    }
    
    

    然后我们创建AppComponet和AppModule

    package com.example.daggertest2;
    
    import javax.inject.Singleton;
    
    import dagger.Component;
    @Singleton
    @Component(modules = AppModule.class)
    public interface AppComponet {
        //这里不需要提供inject方法,因为我们不需要注入,是依附于其它的Conmponent
    }
    
    

    我们在AppModule类中提供CallNets的单例

    
    import android.util.Log;
    
    import javax.inject.Singleton;
    
    import dagger.Module;
    import dagger.Provides;
    
    @Module
    public class AppModule {
        @Singleton
        @Provides
        public CallNets getCallNets(){
            CallNets callNets=new CallNets();
            Log.i("zhang_xin",callNets.toString());
            return callNets;
        }
    }
    
    

    然后修改LoginComponent UserComponent

    package com.example.daggertest2;
    
    import javax.inject.Singleton;
    
    import dagger.Component;
    
    /**
     * 1,在这里我解释下,我们的UserModule并没有提供CallNets实例,如果Dagger在UserModule中没有发现CallNets实例
     * 他就会去依赖既AppComponet.class里面去找.
     * 2,这里不能有@Singleton注释,因为Component的dependencies与Component
     * 自身的scope不能相同
     */
    
    @Component(modules=UserModule.class,dependencies = AppComponet.class)
    public interface LoginComponet {
        void inject(LoginActivity activity);
    
    }
    
    
    package com.example.daggertest2;
    
    import javax.inject.Singleton;
    
    import dagger.Component;
    
    /**
     * 2,这里不能有@Singleton注释,因为Component的dependencies与Component
     * 自身的scope不能相同
     */
    @Component(modules = UserModule.class,dependencies = AppComponet.class)
    public interface UserComponet {
        void inject(MainActivity activity);
    }
    
    

    这里我做下说明


    dagger1.ng.png

    注意第五点,所以我们没办法给LoginComponent和AppComponent添加@Singleton注释,既然没办法添加@Singleton注释,那么我们该怎么给LoginComponent和AppComponent添加注释呢?因为Dagger给我们提供的注释只有@Singleton,所以需要我们自己定义注释。

    package com.example.daggertest2;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.Retention;
    
    import javax.inject.Scope;
    
    import static java.lang.annotation.RetentionPolicy.RUNTIME;
    
    @Scope
    @Documented
    @Retention(RUNTIME)
    public @interface ActivityScope {
    }
    
    

    @scope注明是Scope
    @documented标记在文档
    @Retention 级别,有source class runtime

    然后我们修改LoginComponent和UserComponent文件,添加@ActivityScope 注释。

    package com.example.daggertest2;
    
    import javax.inject.Singleton;
    
    import dagger.Component;
    
    /**
     * 1,在这里我解释下,我们的UserModule并没有提供CallNets实例,如果Dagger在UserModule中没有发现CallNets实例
     * 他就会去依赖既AppComponet.class里面去找.
     * 2,这里不能有@Singleton注释,因为Component的dependencies与Component
     * 自身的scope不能相同
     */
    @ActivityScope//添加该注释
    @Component(modules=UserModule.class,dependencies = AppComponet.class)
    public interface LoginComponet {
        void inject(LoginActivity activity);
    
    }
    
    
    package com.example.daggertest2;
    
    import dagger.Component;
    
    /**
     * 2,这里不能有@Singleton注释,因为Component的dependencies与Component
     * 自身的scope不能相同
     */
    @ActivityScope//添加该注释
    @Component(modules = UserModule.class,dependencies = AppComponet.class)
    public interface UserComponet {
        void inject(MainActivity activity);
    }
    
    

    然后修改AppComponent类

    package com.example.daggertest2;
    
    import javax.inject.Singleton;
    
    import dagger.Component;
    @Singleton
    @Component(modules = AppModule.class)
    public interface AppComponet {
     Conmponent
        CallNets getCallNets();
    }
    
    

    在这里我们做一个桥接,这里的CallNets对象就是由AppModule提供的。
    我们现在reBuild工程,已经可以了没有报错
    可是我们现在又面临一个问题,接下来我们该怎样在LoginActivity和MainActivity中使用AppComponent呢?
    DaggerUserComponet.builder().userModule(new UserModule()).appComponet();
    我们可以看到appComponent()需要传入AppComponet类型的对象,在这里我们怎么给appComponent()传入参数呢?
    因为Singleton是application级别的,所以我们需要在Application中将AppComponent实例化。创建MyApplication继承Application。

    package com.example.daggertest2;
    
    import android.app.Application;
    import android.util.Log;
    
    public class MyApplication extends Application {
        private AppComponet appComponet;
        @Override
        public void onCreate() {
            super.onCreate();
           appComponet= DaggerAppComponet.create();
        }
    
        public AppComponet getAppComponet() {
            return appComponet;
        }
    }
    
    

    然后我们就可以在MainActivity 和LoginActivity里调用了

    package com.example.daggertest2;
    
    import android.content.Intent;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    
    import javax.inject.Inject;
    
    public class MainActivity extends AppCompatActivity {
        @Inject
        UserManager userManager;
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            DaggerUserComponet.builder().userModule(new UserModule())
                    .appComponet(((MyApplication) getApplication())
                            .getAppComponet()).build().inject(this);
            userManager.register();
            startActivity(new Intent(this, LoginActivity.class));
        }
    }
    
    
    package com.example.daggertest2;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    
    import javax.inject.Inject;
    
    public class LoginActivity extends AppCompatActivity {
       @Inject
        UserManager userManager;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_login);
            DaggerLoginComponet.builder().userModule(new UserModule())
                    .appComponet(((MyApplication) getApplication())
                            .getAppComponet()).build().inject(this);
             userManager.register();
        }
    }
    
    

    这样我们就实现了单例模式
    我们在ApiService中添加打印数据,测试下是不是单例模式

    package com.example.daggertest2;
    
    import android.util.Log;
    
    public class ApiService {
        private CallNets callNets;
    
        public ApiService(CallNets callNets) {
            this.callNets = callNets;
        }
    
        public void register() {
            Log.i("zhang_xin", "apiService注册成功"+this.callNets.toString());
        }
    }
    
    

    看下打印结果

    10-24 16:22:59.691 2967-2967/com.example.daggertest2 I/zhang_xin: apiService注册成功com.example.daggertest2.CallNets@4a7ac880
    10-24 16:22:59.701 2967-2967/com.example.daggertest2 I/zhang_xin: apiService注册成功com.example.daggertest2.CallNets@4a7ac880
    
    

    OK,大功告成!

    第九部分:SubComponent

    这里我就强调两点
    1,SubComponent同时具备两种不同生命周期的scope,Subcomponent具备了父Component的scope,也具备自己的Scope
    2,subComponent的Scope范围小于父Component

    第十部份:Lazy与Provider

    相关文章

      网友评论

      本文标题:王学岗 Dagger2的使用从简单到复杂

      本文链接:https://www.haomeiwen.com/subject/xalmzftx.html