Dagger2 进一步解读

一.在我们编程中可能回出现下面的情况
有一个类会在多个类中用到,这时我们想依赖注入,就会出现一个Module对象注入到多个调用者中的情况
这时候我们应该怎么做呢?
在这里我要说明一下Module 和桥梁 Component 是成对存在的
1.定义一个顶级的Module
这个module 提供了 Context
@Module public class AppModule { 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 标记
@Module public class ActivityMoudule { @Named ( "Context" ) // 通过context创建Person 对象 @Provides Person providePersonContext(Context context){ // 此方法需要Context 对象 return new Person(context); } @Named ( "name" ) // 通过name创建Person 对象 @Provides Person providePersonName(){ // 此方法需要name return new Person( "1234" ); }}

使用时,也需要添加此标记
public class MainActivity extends AppCompatActivity { @Named ( "context" ) // 标记 @Inject Person person; @Named ( "name" ) // 标记 @Inject Person person2; @Override protected void 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 )
自定义两个注解,分别对应 Context name
@Qualifier // 关键词 @Retention (RetentionPolicy.RUNTIME) // 运行时仍可用 public @ interface PersonForContext { // Context 对象的注解 }

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

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




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值