zoukankan      html  css  js  c++  java
  • Dagger2

    Dagger是一个完全静态的,在编译时进行依赖注入的框架,原来是由Square公司维护的然后现在把这堆东西扔给Google维护了。Dagger解决了基于反射带来的开发和性能上的问题(因为Dagger并没有用反射来做依赖注入)说了那么多,其实就是告诉我们这家伙可以用来做依赖注入哦。

    依赖注入:我们在做项目时,经常需要在一个对象里去创建另一个对象的实例,这种行为是产生耦合的常见形式,对于一个大型项目来说,过多的相互依赖会导致代码难以维护,很容易就会碰到修改一个小需求需要大面积的修改各种代码,特别是代码原来不是自己维护的,撸着代码的你就开始问候别人家的亲友了。

    在需要依赖的类中不要通过new来创建依赖而是通过方法提供的参数注入进来,这样我们的需要依赖的类和提供依赖的类的实现方法分隔开了,一切又变得如此美好咯。

    dagger2是一个依赖注入框架,在编译期间自动生成代码,负责依赖对象的创建。

    用dagger2提供依赖有什么好处:为了进一步解耦和方便测试,我们会使用依赖注入的方式构建对象 (不使用 new 来创建依赖对象)。在mvp中,presenter层会持有view和model层的依赖,依赖注入主要用于解耦,通过依赖注入创建对象,不再使用new来创建对象。

    依赖注入的目的是:给你提供一个对象依赖。


    Dagger2的常用注解: 
    @Inject:此注解用于告诉Dagger2,我们需要这个类的实例对象。主要用于标记哪个类是需要注入的。
    @Module:此注解里面全是方法,用于对外提供对象,自己定义方法,方法上使用@Provides。自定义一个类,以Module结尾,用@Module注解。
    @Provides:此注解用于标记方法,表示可以通过这个方法获取一个对象,一般用于自定义类中。
    @Component:此注解主要用于关联自定义module类和MainActivity;关联module使用:@Component(modules={UserModule.class});关联Activity,以方法参数的形式传入MainActivity到连接器中

    @Named与@Qualifier:用于区别不同对象的实例。必须要成对出现,否则会报错。

    @PerActivity:限定对象的生命周期和Activity一样。一般应用于自定义的Component上。

    @Singleton:标记为单例模式,如果在自定义Module中使用了此注解,在自定义的Component上也要使用该注解。

     

    使用方式:

    1)自定义Module,里面的方法用于提供依赖,

    2)自定义Component接口,里面全是Activity的注入方法,

    3)按Ctrl+F9进行编译。

     

     

    自定义Module类:

    自定义module中的方法 要以provide开头

    通过构造方法传递Context

     

    如果定义的module,需要传参数,就需要在Activity使用build进行诸如

     

    添加依赖:

    //添加依赖  
    compile 'com.google.dagger:dagger:2.9'  
    annotationProcessor 'com.google.dagger:dagger-compiler:2.9'  
    

    MainActivity代码:此依赖注入的目的是获取ApiService类的实例,然后调用其中的register方法;编译后会自动生成DaggerUserComponent类

    package com.example.administrator.testdragger2.old;  
      
    import android.support.v7.app.AppCompatActivity;  
    import android.os.Bundle;  
    import com.example.administrator.testdragger2.R;  
    import javax.inject.Inject;  
      
    public class MainActivity extends AppCompatActivity {  
          
        @Inject  
        ApiService apiService;  
          
        @Override  
        protected void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.activity_main);  
              
            //Dagger会自动创建这个类,以Dagger开头+UserComponent  
            DaggerUserComponent.create().inject(this);  
            apiService.register();  
              
        }  
    }
    

    UserComponent代码:自定义接口

    package com.example.administrator.testdragger2.old;  
      
    import dagger.*;  
      
    /** 
     * Created on 2017/5/8. 
     * Author:crs 
     * Description: UserComponent连接器,桥梁 
     */  
    @Component(modules = {UserModule.class})  
    public interface UserComponent {  
        //当前只能写MainActivity,不能写Activity,要不然会出现空指针。  
        void inject(MainActivity activity);  
    } 
    

    UserModule代码:自定义module类,主要用于提供依赖

    package com.example.administrator.testdragger2.old;  
      
    import dagger.Module;  
    import dagger.Provides;  
      
    /** 
     * Created on 2017/5/8. 
     * Author:crs 
     * Description:用于提供依赖 
     */  
      
    @Module  
    public class UserModule {  
      
        @Provides  
        ApiService provideApiService(){  
            return new ApiService();  
        }  
    }  
    

    ApiService类:

    package com.example.administrator.testdragger2.old;  
      
    import android.util.Log;  
      
    /** 
     * Created on 2017/5/8. 
     * Author:crs 
     * Description:ApiService 
     */  
    public class ApiService {  
      
        private static final String TAG = "ApiService";  
      
        public void register() {  
            //请求网络数据  
            Log.i(TAG,"测试数据");  
      
        }  
    }
    

    如果自定义类module中的方法,需要一个对象参数,怎么处理?需要一个方法去提供这个对象。

    1)在类的构造方法上添加@Inject注解

    2)自己写一个方法去提供参数对象

    package com.example.administrator.testdaggger2;  
      
    import android.support.v7.app.AppCompatActivity;  
    import android.os.Bundle;  
    import javax.inject.Inject;  
      
    public class MainActivity extends AppCompatActivity {  
      
      
        @Inject  
        UserStore userStore;  
      
        @Inject  
        UserManager userManager;  
      
        @Override  
        protected void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.activity_main);  
              
            //主要两个问题:  
            //1)自定义Module需要传递上下文怎么办  
            //2)自定义Module中的方法中需要参数对象怎么处理?(构造函数、自己提供方法)  
      
            //Dagger会自动创建这个类,以Dagger开头+UserComponent,编译时注入,按Ctrl+F9编辑即可  
            //DaggerUserComponnent.create().inject(this);  
            //userManager.register();  
      
            //Dagger的关系非常简单,MainActivity中需要对象,那么就在Module中提供对象;而他们之间的桥梁就是componnent  
      
            //自定义类Module的构造方法中需要传入一个上下文对象,那么在MainActivity中就需要传递进去。  
            //使用下面的这种方式进行参数传递:this就是上下文  
            DaggerUserComponnent.builder().userModule(new UserModule(this)).build().inject(this);  
            userManager.register();  
      
        }  
    } 
    
    package com.example.administrator.testdaggger2;  
      
    import android.content.Context;  
      
    import dagger.Module;  
    import dagger.Provides;  
      
    /** 
     * Created on 2017/5/9. 
     * Author:crs 
     * Description:XXX 
     */  
    @Module  
    public class UserModule {  
      
        //在Module中传递上下文对象  
        private Context mContext;  
        public UserModule(Context context) {  
            this.mContext = context;  
        }  
        @Provides  
        UserStore provideUserStore(){  
            return new UserStore();  
        }  
      
        //如果自定义Module中的方法需要对象参数,怎么处理?  
        //1)通过Module中的方法进行提供,比如provideUserStore()  
        //2)通过类的构造函数进行提供对象,注释掉上面的provideUserStore()方法  
        //3)代码执行顺序:创建参数对象的方法先执行,比如构造;  
        @Provides  
        UserManager provideUserManager(UserStore userStore) {  
            return new UserManager(userStore);  
        }  
      
    }
    
    package com.example.administrator.testdaggger2;  
      
    import android.util.Log;  
      
    import javax.inject.Inject;  
      
    /** 
     * Created on 2017/5/9. 
     * Author:crs 
     * Description:UserStore 用户数据存储 
     */  
    public class UserStore {  
        //通过构造函数提供依赖  
        @Inject  
        public UserStore() {  
        }  
      
        private static final String TAG = "UserStore";  
      
        public  void register(){  
            Log.i(TAG,"测试数据");  
      
        }  
    }
    

    模块化开发:自定义module之间相互include,component之间相互依赖

    通过@Named @Qualifier:区别不同对象的实例

    同一个类,可能要创建两个对象,处理不同的业务逻辑
    通过类型进行注入,根据@Inject标记的变量类型ApiService,在Module中寻找返回值为ApiService的方法进行调用。但是如果Module中有多个方法,它们的返回值都为ApiService,那么就需要使用@Named注解用于区别。(区分不同对象的实例@Qualifier)
    比如:访问测试服务器,访问正式服务器

    代码如下:

    package com.example.administrator.testdragger2.dagger2;  
      
    import android.os.Bundle;  
    import android.support.annotation.Nullable;  
    import android.support.v7.app.AppCompatActivity;  
    import android.util.Log;  
      
    import com.example.administrator.testdragger2.R;  
      
      
    import javax.inject.Inject;  
    import javax.inject.Named;  
      
    /** 
     * Created on 2017/5/9. 
     * Author:crs 
     * Description:TestMainActivity 
     */  
    public class TestMainActivity extends AppCompatActivity {  
          
        private static final String TAG ="TestMainActivity" ;  
        //访问测试服务器  
        @Named("dev")  
        @Inject  
        ApiService apiServiceDev;  
      
        //访问正式服务器  
        @Named("release")  
        @Inject  
        ApiService apiServiceRelease;  
          
        @Override  
        protected void onCreate(@Nullable Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.activity_test);  
      
            DaggerUserComponent.builder().httpModule(new HttpModule()).userModule(new UserModule(this)).build().inject(this);  
            //此时这两个两个对象的内存地址是不一样的  
            Log.i(TAG,apiServiceDev.toString());  
            Log.i(TAG,apiServiceRelease.toString());  
      
            //apiServiceDev.register();  
            //apiServiceRelease.register();  
        }  
    } 
    

    Component连接两个Module(可以连接多个Module)

    package com.example.administrator.testdragger2.dagger2;  
      
    import dagger.Component;  
      
    /** 
     * Created on 2017/5/9. 
     * Author:crs 
     * Description:UserComponent 
     */  
    @Component(modules={UserModule.class,HttpModule.class})  
    public interface UserComponent {  
        void inject(TestMainActivity activity);  
    }
    

    UserModule包含HttpModule

    package com.example.administrator.testdragger2.dagger2;  
      
    import android.content.Context;  
      
    import javax.inject.Named;  
      
    import dagger.Module;  
    import dagger.Provides;  
    import okhttp3.OkHttpClient;  
      
    /** 
     * Created on 2017/5/9. 
     * Author:crs 
     * Description:自定义Module类 
     */  
    //表示当前module引用HttpModule,进而提供OkHttpClient的对象  
    @Module(includes = {HttpModule.class})  
    public class UserModule {  
      
        private Context mContext;  
        UserModule(Context context) {  
            this.mContext=context;  
        }  
      
        //此时缺少OkHttpClient的实例,并且当前自定义Module中并没有提供,如何处理?  
        @Named("dev")  
        @Provides  
        ApiService provideApiServiceDev(OkHttpClient client){  
            return new ApiService(client);  
        }  
      
        @Named("release")  
        @Provides  
        ApiService provideApiServiceRelease(OkHttpClient client){  
            return new ApiService(client);  
        }  
    }
    
    package com.example.administrator.testdragger2.dagger2;  
      
    import java.io.IOException;  
      
    import javax.inject.Inject;  
      
    import okhttp3.Call;  
    import okhttp3.Callback;  
    import okhttp3.OkHttpClient;  
    import okhttp3.Request;  
    import okhttp3.RequestBody;  
    import okhttp3.Response;  
      
    /** 
     * Created on 2017/5/9. 
     * Author:crs 
     * Description:ApiService网络请求 
     */  
    public class ApiService {  
        //常用类:OKHttpClient,Request,RequestBody,CallBack  
      
        OkHttpClient client;  
      
        //构造函数  
        @Inject  
        public ApiService(OkHttpClient client) {  
            this.client=client;  
        }  
      
      
        //主要用于网络请求  
        public void register(){  
            RequestBody body=RequestBody.create(null,"");  
            Request request = new Request.Builder()  
                    .url("")  
                    .post(body)  
                    .build();  
            client.newCall(request).enqueue(new Callback() {  
                @Override  
                public void onFailure(Call call, IOException e) {  
      
                }  
      
                @Override  
                public void onResponse(Call call, Response response) throws IOException {  
      
                }  
            });  
        }  
    } 
    

      

  • 相关阅读:
    Eureka 注册中心 简单搭建
    Eclipse properties.config.yml 配置文件中文编码问题。Eclipse 配置文件插件解决方案
    OracleDBConsole启动不了
    Codeforces Round #275(Div. 2)-C. Diverse Permutation
    Codeforces Round #275 (Div. 2)-B. Friends and Presents
    Codeforces Round #275 (Div. 2)-A. Counterexample
    NYOJ-106-背包问题
    NYOJ-71-独木舟上的旅行
    NYOJ-91-阶乘之和
    BestCoder Round#15 1002-Instruction
  • 原文地址:https://www.cnblogs.com/foxy/p/7850431.html
Copyright © 2011-2022 走看看