Dagger2 进一步解读

来源:互联网 发布:北通安卓手柄映射软件 编辑:程序博客网 时间:2024/06/06 14:22
一.在我们编程中可能回出现下面的情况
有一个类会在多个类中用到,这时我们想依赖注入,就会出现一个Module对象注入到多个调用者中的情况
这时候我们应该怎么做呢?
在这里我要说明一下Module 和桥梁Component是成对存在的
1.定义一个顶级的Module
这个module 提供了Context
@ModulepublicclassAppModule {private Context mContext;public AppModule(Context context){ mContext = context; }@Provides Context providesContext(){// 提供Context对象 return mContext; }}

现在我们有两个或以上的调用者用到Context 对象
所以我们就要定义下层的多个module,获取到Context

2.所以我们要将顶级Module 的Context 提供出去

//顶级Module 的桥梁@Component(modules = AppModule.class)public interface AppComponent {// 向其下层提供Context 对象 Context proContext();}

3.下层Module获得 Context
// 下层Module类@Modulepublic class ActivityMoudule { @Provides Person providePerson(Context context){ // 此方法需要Context 对象
//上层传过来的Context 对象 return new Person(context); }}
4.下层Module 的桥梁提供给调用者
//下层Module 的桥梁@Component(dependencies = AppComponent.class,modules = ActivityMoudule.class)public interface ActivityComponent { // 注入 void inject(MainActivity activity);}

5.调用者被注入
// 顶级依赖对象 Component AppComponent appCom = DaggerAppComponent.builder().appModule(new AppModule(this)).build(); // 子类依赖对象 ,并注入 DaggerActivityComponent.builder() .appComponent(appCom) .activityMoudule(new ActivityMoudule()) .build() .inject(this);



二.@Qualifier 自定义标记
在使用中,会出现两个方法返回对象相同时的情况,那么如何区分呢。
@Qualifier:当类的类型不足以鉴别一个依赖的时候,我们就可以使用这个注解标示。例如:在Android中,我们会需要不同类型的context,所以我们就可以定义 qualifier注解“@perApp”和“@perActivity”,这样当注入一个context的时候,我们就可以告诉 Dagger我们想要哪种类型的context。
我的理解就是,当要注入的对象的类型不能确定是唯一的,这时就要自定义注解用来标记注入的具体是那个类
例:参数是Content ,我们可以传入Activity或者Application 这样我们就定义两个注解标记

举个栗子:
bean类Person 中有两个构造器 通过传入不同的参数来实例化对象
public class Person { private Context mContext; public Person(Context context){ mContext = context; Log.i("dagger","create"); } public Person(String name){ Log.i("dagger",name); }}
这种情况注入依赖:
第一种方式:这种方式和Qualifier无关
ActivityModule中添加@Named标记
@ModulepublicclassActivityMoudule {@Named("Context")// 通过context创建Person 对象@Provides Person providePersonContext(Context context){// 此方法需要Context 对象returnnew Person(context); }@Named("name")// 通过name创建Person 对象@Provides Person providePersonName(){// 此方法需要namereturnnew Person("1234"); }}

使用时,也需要添加此标记
publicclassMainActivityextendsAppCompatActivity{@Named("context")// 标记@Inject Person person;@Named("name")// 标记@Inject Person person2;@Overrideprotectedvoid onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);//注入 component.inject(this);*/// 依赖对象 Component AppComponent appCom = DaggerAppComponent.builder().appModule(new AppModule(this)).build();// 子类依赖对象 ,并注入 DaggerActivityComponent.builder() .appComponent(appCom) .activityMoudule(new ActivityMoudule()) .build() .inject(this); } }
使用时,使用者的@Inject上,必须要加入注解@Named("xxx"),不然编译期会报错。
这样使用过程中,虽然解决了问题,但是通过字符串标记一个对象,容易导致前后不匹配,

第二种方式:自定义注解(@Qualifier)
自定义两个注解,分别对应Contextname
@Qualifier// 关键词@Retention(RetentionPolicy.RUNTIME)// 运行时仍可用public @interfacePersonForContext {// Context 对象的注解}

@Qualifier@Retention(RetentionPolicy.RUNTIME)public @interfacePersonForName {// name 对象的注解}

在使用@Named("")的地方替换为自定义的注解
@PersonForContext// 通过context创建Person 对象@Provides Person providePersonContext(Context context){// 此方法需要Context 对象returnnew Person(context); }@PersonForName// 通过name创建Person 对象@Provides Person providePersonName(){// 此方法需要Context 对象returnnew Person("123"); }
注入时:
@PersonForContext// 标记@Inject Person person;@PersonForName// 标记@Inject Person person2;




0 0
原创粉丝点击