Dagger2的使用与理解(2)
来源:互联网 发布:数据防泄密方案 编辑:程序博客网 时间:2024/05/29 02:30
接下来我们来看看@Module注解和@Provides注解,他们两个是在一起配合使用的。
@Module这个注解是用来修饰类对象的,表示这个类是个模板类,里面的@Provides修饰的方法的返回值用来提供依赖,所以@Provides修饰的方法必须不能是void,否则编译会报错。
为什么要使用这两个注解呢?
因为使用@Inject标记构造器提供依赖是有局限性的,比如说我们需要注入的对象是第三方库提供的,我们无法在第三方库的构造器上加上@Inject注解。
或者是需要注入的对象是抽象的,@Inject也无法使用,因为抽象的类并不能实例化。因为我们依赖的生成是直接通过new 出来,抽象类无法直接实现,因为生成代码无法确定抽象方法的实现。详情请见Dagger2的使用与理解(1)
首先我们新建一个Module类,这里用来为Activity提供Module,所以命名为ActivityModule,ActivityModule用@Module修饰表示这是个模板类,里面有两个用@Provides修饰的方法,分别用来提供String类型的依赖和Person类型的依赖。这里Person是个抽象类,Men类和Woman类继承Person类。
@Modulepublic class ActivityModule { @Provides public String obtain(){ return "1234"; } @Provides public Person privodePerson(){ return new Women(); }}
//抽象Person类实现public abstract class Person {}//具体实现的子类--男人类public class Men extends Person {}//具体实现的子类--女人类public class Women extends Person {}
在对应的注入器添加@Component里面的参数,参数就是用@Module修饰的Module类对象。
@Component(modules = ActivityModule.class)public interface ActivityComponent { void inject(DaggerActivity daggerActivity);}
在Activity注入
public class DaggerActivity extends AppCompatActivity { @Inject String sss; @Inject Person person; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_gui_view); DaggerActivityComponent.create().inject(this); Log.e("TAG", "sss = " + sss); Log.e("TAG", "person = " + person); }}
打印输出的结果是 sss = 1234 person = 引用值,说明成员变量已经被注入依赖
@Module需要和@Provides是需要一起使用的时候才具有作用的,@Module是告诉Component,可以从这里获取依赖对象。Component就会去找被@Provide标注的方法,相当于构造器的@Inject,可以提供依赖。
还有一点要说的是,@Component可以指定多个@Module的,如果需要提供多个依赖的话。
@Component(modules = {Module1.class, Module2.class})public interface ActivityComponent { void inject(DaggerActivity daggerActivity);}
那么他在DaggerActivityComponent方法是怎么注入的呢,首先在成员变量多了两个Provider对象,也就是我们在Module类写的返回方法的依赖。
private Provider<String> obtainProvider; private Provider<Person> privodePersonProvider; private MembersInjector<DaggerActivity> daggerActivityMembersInjector;
接下去看他们的初始化,在initialize方法,将module对象传入。
private void initialize(final Builder builder) { this.obtainProvider = ActivityModule_ObtainFactory.create(builder.activityModule); this.privodePersonProvider = ActivityModule_PrivodePersonFactory.create(builder.activityModule); this.daggerActivityMembersInjector = DaggerActivity_MembersInjector.create((MembersInjector) MembersInjectors.noOp(), obtainProvider, privodePersonProvider); }
而Module是Builder的成员变量,可以外部传入Module,也可以通过build()方法创建。
public static final class Builder { private ActivityModule activityModule; private Builder() { } public ActivityComponent build() { if (activityModule == null) { this.activityModule = new ActivityModule(); } return new DaggerActivityComponent(this); } public Builder activityModule(ActivityModule activityModule) { if (activityModule == null) { throw new NullPointerException("activityModule"); } this.activityModule = activityModule; return this; }
上面创建的Module传入Provider的工厂实现上,我们重点看一下get方法,他将返回module.obtain()的返回值,而这个函数就是我们之前用@Provides注解标记的方法,return “1234”。Person的Provider实现同String。最后在注入的依赖的时候就能够将module类中用@Provides注解标记的方法的返回值赋值给注入对象。
public final class ActivityModule_ObtainFactory implements Factory<String> { private final ActivityModule module; public ActivityModule_ObtainFactory(ActivityModule module) { assert module != null; this.module = module; } @Override public String get() { String provided = module.obtain(); if (provided == null) { throw new NullPointerException("Cannot return null from a non-@Nullable @Provides method"); } return provided; } public static Factory<String> create(ActivityModule module) { return new ActivityModule_ObtainFactory(module); }}
这里注意一点,我们可以这么去写,在ActivityComponent 中加入provideB()和provideStr()方法,发现编译成功。其实这也是ActivityComponent 一个重要的功能,他能显示把项目里的依赖提供出来,暴露出去。B就是有@Inject标注构造器的依赖,String就是ActivityModule里面的”1234”。
@Component(modules = ActivityModule.class)public interface ActivityComponent { void inject(DaggerActivity daggerActivity); B provideB(); String provideStr();}
@Override public B provideB() { return B_Factory.create().get(); } @Override public String provideStr() { return obtainProvider.get(); }
@Qualifier和@Named这两个注解是用来区分同类依赖的,@Qualifier是限定符,而@Named则是基于String的限定符。
当我有两个相同的依赖(都继承某一个父类或者都是先某一个接口)可以提供给高层时,那么程序就不知道我们到底要提供哪一个依赖,因为它找到了两个。
这时候我们就可以通过限定符为两个依赖分别打上标记,指定提供某个依赖。举个栗子:
//修改ActivityModule代码,其余代码不变@Modulepublic class ActivityModule { @Provides public String obtain(){ return "1234"; } @Provides public Person privodeWoman(){ return new Women(); } @Provides public Person privodeMan(){ return new Men(); }}
编译出错
因为在不知道用哪个Person(是来自privodeWoman(),还是来自privodeMan())依赖来注入。解决办法如下:
@Provides @Named("woman") public Person privodeWoman(){ return new Women(); } @Provides @Named("man") public Person privodeMan(){ return new Men(); }
注入的时候在person上面加上@Named(“woman”),person就会被注入Woman的实例。
//这里选择Woman,女士优先嘛@Inject @Named("woman") Person person;
或者使用@Qualifier,@Qualifier不是直接注解在属性上的,而是用来自定义注解的。
@Target(ANNOTATION_TYPE)@Retention(RUNTIME)@Documentedpublic @interface Qualifier {}
我们新建两个注解@ManQualifier,@WomanQualifier,
@Qualifier@Retention(RetentionPolicy.RUNTIME)public @interface ManQualifier {}@Qualifier@Retention(RetentionPolicy.RUNTIME)public @interface WomanQualifier {}
这个Module类改为:
@Modulepublic class ActivityModule { @Provides public String obtain(){ return "1234"; } @Provides @WomanQualifier public Person privodeWoman(){ return new Women(); } @Provides @ManQualifier public Person privodeMan(){ return new Men(); }}
在person类上面用@ManQualifier注解修饰,这样就能把Man的实例注入到person中。
@Inject @ManQualifier Person person;
今天就写这些吧。。。。
- Dagger2的使用与理解(2)
- Dagger2的使用与理解(1)
- Dagger2的使用与理解(3)
- Dagger2的使用与理解(4)
- Dagger2的使用(2)
- Dagger2的了解与使用
- Dagger2 学习与理解
- Dagger2自己的理解
- android框架学习篇-Dagger2的理解与应用
- 一些关于dagger2的理解
- 我所理解的Dagger2
- 我所理解的Dagger2
- dagger2框架的学习理解
- 我对Dagger2的理解
- Dagger2的使用
- 对Dagger2的使用
- Dagger2的使用
- Dagger2的简单使用
- 从Chrome源码看JS Array的实现
- jsp中Object的如何转换
- c++作业6
- C++作业6-数组2
- 田忌赛马
- Dagger2的使用与理解(2)
- Linux命令基础36-tar压缩包和解压命令
- python字符串之'\x00'与空串''的区别
- SpringMVC学习(五)——SpringMVC的参数绑定
- 一步之遥
- 学习MVC之租房网站(十一)-定时任务和云存储
- redis.conf的配置
- 五、Canvas控件
- ①写给后端工程师的JavaScript教程——从这里开始