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进行诸如



添加依赖:

[java]  view plain  copy
  1. //添加依赖  
  2. compile 'com.google.dagger:dagger:2.9'  
  3. annotationProcessor 'com.google.dagger:dagger-compiler:2.9'  

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

[java]  view plain  copy
  1. package com.example.administrator.testdragger2.old;  
  2.   
  3. import android.support.v7.app.AppCompatActivity;  
  4. import android.os.Bundle;  
  5. import com.example.administrator.testdragger2.R;  
  6. import javax.inject.Inject;  
  7.   
  8. public class MainActivity extends AppCompatActivity {  
  9.       
  10.     @Inject  
  11.     ApiService apiService;  
  12.       
  13.     @Override  
  14.     protected void onCreate(Bundle savedInstanceState) {  
  15.         super.onCreate(savedInstanceState);  
  16.         setContentView(R.layout.activity_main);  
  17.           
  18.         //Dagger会自动创建这个类,以Dagger开头+UserComponent  
  19.         DaggerUserComponent.create().inject(this);  
  20.         apiService.register();  
  21.           
  22.     }  
  23. }  
UserComponent代码:自定义接口

[java]  view plain  copy
  1. package com.example.administrator.testdragger2.old;  
  2.   
  3. import dagger.*;  
  4.   
  5. /** 
  6.  * Created on 2017/5/8. 
  7.  * Author:crs 
  8.  * Description: UserComponent连接器,桥梁 
  9.  */  
  10. @Component(modules = {UserModule.class})  
  11. public interface UserComponent {  
  12.     //当前只能写MainActivity,不能写Activity,要不然会出现空指针。  
  13.     void inject(MainActivity activity);  
  14. }  
UserModule代码:自定义module类,主要用于提供依赖

[java]  view plain  copy
  1. package com.example.administrator.testdragger2.old;  
  2.   
  3. import dagger.Module;  
  4. import dagger.Provides;  
  5.   
  6. /** 
  7.  * Created on 2017/5/8. 
  8.  * Author:crs 
  9.  * Description:用于提供依赖 
  10.  */  
  11.   
  12. @Module  
  13. public class UserModule {  
  14.   
  15.     @Provides  
  16.     ApiService provideApiService(){  
  17.         return new ApiService();  
  18.     }  
  19. }  
ApiService类:

[java]  view plain  copy
  1. package com.example.administrator.testdragger2.old;  
  2.   
  3. import android.util.Log;  
  4.   
  5. /** 
  6.  * Created on 2017/5/8. 
  7.  * Author:crs 
  8.  * Description:ApiService 
  9.  */  
  10. public class ApiService {  
  11.   
  12.     private static final String TAG = "ApiService";  
  13.   
  14.     public void register() {  
  15.         //请求网络数据  
  16.         Log.i(TAG,"测试数据");  
  17.   
  18.     }  
  19. }  

———————————————————————————————————————>

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

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

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

[java]  view plain  copy
  1. package com.example.administrator.testdaggger2;  
  2.   
  3. import android.support.v7.app.AppCompatActivity;  
  4. import android.os.Bundle;  
  5. import javax.inject.Inject;  
  6.   
  7. public class MainActivity extends AppCompatActivity {  
  8.   
  9.   
  10.     @Inject  
  11.     UserStore userStore;  
  12.   
  13.     @Inject  
  14.     UserManager userManager;  
  15.   
  16.     @Override  
  17.     protected void onCreate(Bundle savedInstanceState) {  
  18.         super.onCreate(savedInstanceState);  
  19.         setContentView(R.layout.activity_main);  
  20.           
  21.         //主要两个问题:  
  22.         //1)自定义Module需要传递上下文怎么办  
  23.         //2)自定义Module中的方法中需要参数对象怎么处理?(构造函数、自己提供方法)  
  24.   
  25.         //Dagger会自动创建这个类,以Dagger开头+UserComponent,编译时注入,按Ctrl+F9编辑即可  
  26.         //DaggerUserComponnent.create().inject(this);  
  27.         //userManager.register();  
  28.   
  29.         //Dagger的关系非常简单,MainActivity中需要对象,那么就在Module中提供对象;而他们之间的桥梁就是componnent  
  30.   
  31.         //自定义类Module的构造方法中需要传入一个上下文对象,那么在MainActivity中就需要传递进去。  
  32.         //使用下面的这种方式进行参数传递:this就是上下文  
  33.         DaggerUserComponnent.builder().userModule(new UserModule(this)).build().inject(this);  
  34.         userManager.register();  
  35.   
  36.     }  
  37. }  

[java]  view plain  copy
  1. package com.example.administrator.testdaggger2;  
  2.   
  3. import android.content.Context;  
  4.   
  5. import dagger.Module;  
  6. import dagger.Provides;  
  7.   
  8. /** 
  9.  * Created on 2017/5/9. 
  10.  * Author:crs 
  11.  * Description:XXX 
  12.  */  
  13. @Module  
  14. public class UserModule {  
  15.   
  16.     //在Module中传递上下文对象  
  17.     private Context mContext;  
  18.     public UserModule(Context context) {  
  19.         this.mContext = context;  
  20.     }  
  21.     @Provides  
  22.     UserStore provideUserStore(){  
  23.         return new UserStore();  
  24.     }  
  25.   
  26.     //如果自定义Module中的方法需要对象参数,怎么处理?  
  27.     //1)通过Module中的方法进行提供,比如provideUserStore()  
  28.     //2)通过类的构造函数进行提供对象,注释掉上面的provideUserStore()方法  
  29.     //3)代码执行顺序:创建参数对象的方法先执行,比如构造;  
  30.     @Provides  
  31.     UserManager provideUserManager(UserStore userStore) {  
  32.         return new UserManager(userStore);  
  33.     }  
  34.   
  35. }  
[java]  view plain  copy
  1. package com.example.administrator.testdaggger2;  
  2.   
  3. import android.util.Log;  
  4.   
  5. import javax.inject.Inject;  
  6.   
  7. /** 
  8.  * Created on 2017/5/9. 
  9.  * Author:crs 
  10.  * Description:UserStore 用户数据存储 
  11.  */  
  12. public class UserStore {  
  13.     //通过构造函数提供依赖  
  14.     @Inject  
  15.     public UserStore() {  
  16.     }  
  17.   
  18.     private static final String TAG = "UserStore";  
  19.   
  20.     public  void register(){  
  21.         Log.i(TAG,"测试数据");  
  22.   
  23.     }  
  24. }  

———————————————————————————————————————>

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

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

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

代码如下:

[java]  view plain  copy
  1. package com.example.administrator.testdragger2.dagger2;  
  2.   
  3. import android.os.Bundle;  
  4. import android.support.annotation.Nullable;  
  5. import android.support.v7.app.AppCompatActivity;  
  6. import android.util.Log;  
  7.   
  8. import com.example.administrator.testdragger2.R;  
  9.   
  10.   
  11. import javax.inject.Inject;  
  12. import javax.inject.Named;  
  13.   
  14. /** 
  15.  * Created on 2017/5/9. 
  16.  * Author:crs 
  17.  * Description:TestMainActivity 
  18.  */  
  19. public class TestMainActivity extends AppCompatActivity {  
  20.       
  21.     private static final String TAG ="TestMainActivity" ;  
  22.     //访问测试服务器  
  23.     @Named("dev")  
  24.     @Inject  
  25.     ApiService apiServiceDev;  
  26.   
  27.     //访问正式服务器  
  28.     @Named("release")  
  29.     @Inject  
  30.     ApiService apiServiceRelease;  
  31.       
  32.     @Override  
  33.     protected void onCreate(@Nullable Bundle savedInstanceState) {  
  34.         super.onCreate(savedInstanceState);  
  35.         setContentView(R.layout.activity_test);  
  36.   
  37.         DaggerUserComponent.builder().httpModule(new HttpModule()).userModule(new UserModule(this)).build().inject(this);  
  38.         //此时这两个两个对象的内存地址是不一样的  
  39.         Log.i(TAG,apiServiceDev.toString());  
  40.         Log.i(TAG,apiServiceRelease.toString());  
  41.   
  42.         //apiServiceDev.register();  
  43.         //apiServiceRelease.register();  
  44.     }  
  45. }  

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

[java]  view plain  copy
  1. package com.example.administrator.testdragger2.dagger2;  
  2.   
  3. import dagger.Component;  
  4.   
  5. /** 
  6.  * Created on 2017/5/9. 
  7.  * Author:crs 
  8.  * Description:UserComponent 
  9.  */  
  10. @Component(modules={UserModule.class,HttpModule.class})  
  11. public interface UserComponent {  
  12.     void inject(TestMainActivity activity);  
  13. }  
UserModule包含HttpModule

[java]  view plain  copy
  1. package com.example.administrator.testdragger2.dagger2;  
  2.   
  3. import android.content.Context;  
  4.   
  5. import javax.inject.Named;  
  6.   
  7. import dagger.Module;  
  8. import dagger.Provides;  
  9. import okhttp3.OkHttpClient;  
  10.   
  11. /** 
  12.  * Created on 2017/5/9. 
  13.  * Author:crs 
  14.  * Description:自定义Module类 
  15.  */  
  16. //表示当前module引用HttpModule,进而提供OkHttpClient的对象  
  17. @Module(includes = {HttpModule.class})  
  18. public class UserModule {  
  19.   
  20.     private Context mContext;  
  21.     UserModule(Context context) {  
  22.         this.mContext=context;  
  23.     }  
  24.   
  25.     //此时缺少OkHttpClient的实例,并且当前自定义Module中并没有提供,如何处理?  
  26.     @Named("dev")  
  27.     @Provides  
  28.     ApiService provideApiServiceDev(OkHttpClient client){  
  29.         return new ApiService(client);  
  30.     }  
  31.   
  32.     @Named("release")  
  33.     @Provides  
  34.     ApiService provideApiServiceRelease(OkHttpClient client){  
  35.         return new ApiService(client);  
  36.     }  
  37. }  
[java]  view plain  copy
  1. package com.example.administrator.testdragger2.dagger2;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import javax.inject.Inject;  
  6.   
  7. import okhttp3.Call;  
  8. import okhttp3.Callback;  
  9. import okhttp3.OkHttpClient;  
  10. import okhttp3.Request;  
  11. import okhttp3.RequestBody;  
  12. import okhttp3.Response;  
  13.   
  14. /** 
  15.  * Created on 2017/5/9. 
  16.  * Author:crs 
  17.  * Description:ApiService网络请求 
  18.  */  
  19. public class ApiService {  
  20.     //常用类:OKHttpClient,Request,RequestBody,CallBack  
  21.   
  22.     OkHttpClient client;  
  23.   
  24.     //构造函数  
  25.     @Inject  
  26.     public ApiService(OkHttpClient client) {  
  27.         this.client=client;  
  28.     }  
  29.   
  30.   
  31.     //主要用于网络请求  
  32.     public void register(){  
  33.         RequestBody body=RequestBody.create(null,"");  
  34.         Request request = new Request.Builder()  
  35.                 .url("")  
  36.                 .post(body)  
  37.                 .build();  
  38.         client.newCall(request).enqueue(new Callback() {  
  39.             @Override  
  40.             public void onFailure(Call call, IOException e) {  
  41.   
  42.             }  
  43.   
  44.             @Override  
  45.             public void onResponse(Call call, Response response) throws IOException {  
  46.   
  47.             }  
  48.         });  
  49.     }  
  50. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值