概述
Dagger 2 是 Google 开源的一款依靠注入结构,它的前身是 square 的 Dagger 1,Dagger 2 在 Android 中有着较为广泛的运用。
Dagger 2 根据 Java 注解,采用 annotationProcessor(注解处理器) 在项目编译时动态生成依靠注入需求的 Java 代码,然后咱们在合适的位置手动完结终究的依靠注入,而不是 Dagger 1 中根据反射的解决方案,所以在性能上是有保障的。
Dagger2的运用
首要我先用张图来简略阐明一下Dagger2运用的流程
图中的Module是运用中常用的功用模块,比如说网络拜访,数据存储等。这个类会有一个@Module的注解,具体的代码我会在后面具体介绍。其实这个Module的作用是提供各种功用目标,而这些Module会放到一个有@Component的容器类中,也便是图中Component类。当咱们想运用各种功用目标进行事务操作的时分,只需求这个容器就能得到被注册了的功用目标,图中的意思是在Activity中运用目标进行事务操作,当然也不只限于Activity。
上图相对来说仍是太简略了,并没有完好的表达出Dagger2的原理,下面咱们直接从代码中感受一个Dagger2的强大。
1.引入Dagger2
implementation 'com.google.dagger:dagger:2.4'
annotationProcessor 'com.google.dagger:dagger-compiler:2.4'
2.创立网络拜访目标及其Module模块
首要创立一个HttpObject,咱们假定这个HttpObject中有各种网络的操作,get,post,put等
public void get(){
Log.i("Dagger2","这儿是get办法");
}
public void post(){
Log.i("Dagger2","这儿是post办法");
}
}
创立HttpModule
@Module
public class HttpModule {
@Provides
public HttpObject providerHttpObject(){
return new HttpObject();
}
}
HttpModule的两个注解是需求留意的地方:@Module这个注解相当于给当时类打了一个标记,表明了这个类的类型,便于注入到容器中;@Provides这个注解放在了办法的上面,从上面的代码能够看出来,首要便是创立功用目标。
3.创立容器Component
@Component(modules = {HttpModule.class})
public interface MyComponent {
void injectMainActivity(MainActivity mainActivity);
}
容器这个类被@Component所注解,而且是一个接口类,@Component中的modules参数接收的类型是一个数组,表示被装入容器的Module有哪些。injectMainActivity办法表示这个容器中的功用目标(例如HttpObject)会在哪个类运用,我这儿运用的MainActivity做的测试,所以参数写的是MainActivity。
4.在类中运用HttpObject
在装备完上述的代码之后,必定先rebuild!
public class MainActivity extends AppCompatActivity {
@Inject
HttpObject mHttpObject;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerMyComponent.create().injectMainActivity(this);
mHttpObject.get();
mHttpObject.post();
}
}
由于咱们要运用的类是HttpObject,所以在MainActivity创立这个类的目标,然后被@Inject所注解。要留意的是DaggerMyComponent这个类是rebuild之后生成的,调用DaggerMyComponent.create().inkectMainActivity(this)这句话来生成mHttpObject目标,调用HttpObject中的get和post办法就会有相应的输出。
Dagger 2原理
相比机械性的记住这些注解以及运用流程,Dagger 2 背面的作业原理愈加重要,这样咱们将理解各个模块的职责,以及结构是如何将它们关联起来帮助咱们完结依靠注入的,理解了原理后运用 Dagger 2 就会愈加称心如意了。
所以咱们这儿先了解 Dagger 2 背面的根本原理,然后再学习其它内容。
以前边的demo为例,项目编译后会在app\build\generated\source\apt\debug\包名目录下生成依靠注入的相关类,如下:
按照之前说法,DaggerMainComponent是完结依靠注入的中心,所以从这个类开端剖析,它的源码如下:
public final class DaggerMainComponent implements MainComponent {
private MainModule mainModule;
private DaggerMainComponent(Builder builder) {
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.mainModule = builder.mainModule;
}
// 重写inject办法,完结依靠注入
@Override
public void inject(MainActivity activity) {
injectMainActivity(activity);
}
// 完结依靠注入的重要办法
private MainActivity injectMainActivity(MainActivity instance) {
// 给 MainActivity 中的 cat 成员变量赋值
MainActivity_MembersInjector.injectCat(instance, new Cat());
// 给 MainActivity 中的 flower 成员变量赋值
MainActivity_MembersInjector.injectFlower1(
instance, MainModule_ProvideRedRoseFactory.proxyProvideRedRose(mainModule));
return instance;
}
public static final class Builder {
private MainModule mainModule;
private Builder() {}
// 完结DaggerMainComponent目标的创立
public MainComponent build() {
if (mainModule == null) {
this.mainModule = new MainModule();
}
return new DaggerMainComponent(this);
}
// 设置 mainModule 目标
public Builder mainModule(MainModule mainModule) {
this.mainModule = Preconditions.checkNotNull(mainModule);
return this;
}
}
}
典型的 Builder 构建模式,再结合之前 DaggerMainComponent 的用法来剖析:
DaggerMainComponent.builder()
.mainModule(new MainModule())
.build()
.inject(this);
先经过builder()办法创立一个 Builder 目标,再经过其mainModule()办法设置mainModule 目标,接下来用 build()办法便是创立DaggerMainComponent 目标,这样它里面也有了一个mainModule目标。
在 DaggerMainComponent 中还重写了 MainComponent 接口的inject()办法,里面调用的injectMainActivity()办法是完结依靠注入的关键:
private MainActivity injectMainActivity(MainActivity instance) {
MainActivity_MembersInjector.injectCat(instance, new Cat());
MainActivity_MembersInjector.injectFlower1(
instance, MainModule_ProvideRedRoseFactory.proxyProvideRedRose(mainModule));
return instance;
}
首要是调用MainActivity_MembersInjector类的injectCat()办法直接创立一个 Cat 目标,完结 MainActivity 中 cat 的赋值,injectCat()办法声明如下:
public static void injectCat(MainActivity instance, Cat cat) {
instance.cat = cat;
}
然后是调用injectFlower()办法,完结 MainActivity 中 flower 的赋值,那么 flower 目标的值从哪里来呢?这儿调用了MainModule_ProvideRedRoseFactory的proxyProvideRedRose()办法:
public static Flower proxyProvideRedRose(MainModule instance) {
return Preconditions.checkNotNull(
instance.provideRedRose(), "Cannot return null from a non-@Nullable @Provides method");
}
里面终究是调用了咱们在 MainModule 中声明的 provideRedRose() 办法,所以在 DaggerMainComponent 内部是经过 MainActivity_MembersInjector 完结了终究的依靠注入。所以当在 Activity 中履行inject(this)办法时,便是开端创立依靠目标,并完结注入作业。
到这儿整个依靠注入的流程就结束了,从源码的视点来看,整个进程更像是医师给患者打针药物。咱们能够把依靠注入组件 DaggerMainComponent 看做“医师”,把 MainActivity_MembersInjector 看做“打针器”,MainModule 便是“药物”,MainActivity 便是“患者”,医师用打针器把药物送到患者体内。
Dagger的优点
有的小伙伴会问,你整这么一大堆是为了啥?要不然直接创立目标,要不然创立一个单例,多省劲,可比Dagger2的这种方式方便多了。在中大型项目中,类似于HttpObject这种目标会被大量的运用,如果突然有一天这个类的初始化办法改变了,你岂不是要修正每一处吗。即便是运用单例getInstance办法也避免不了这种问题,由于如果在创立目标的时分需求在构造器中增加一个参数,每一处的getInstance也需求被修正。而Dagger2完美的避免了这种问题。
以上便是Android中Dagger 2的根本运用以及原理的学习,有关Android开发中还有更多的学习技术;这儿推荐参阅传送直达↓↓↓ :www.6hu.cc/go//?target=htt…这个大文档里面记录了30多个技术板块。几千个小知识点带你引入更高的技术层面。
总结
Dagger 2 的首要内容就这些了,运用 Dagger 2 必然要编写相关的辅助类、接口、运用各种注解,虽然没有直接 new 一个目标或许传统的依靠注入方式简略,但 Dagger 2 带来的是更好的代码解耦,更有利于后期的扩展保护,关于那些需求长时间保护的项目这一点是愈加重要的。