android dagger2 讲解,告别Dagger2模板代码:DaggerAndroid原理解析
本系列所有文章:
概述
距离我的上一篇文章发布以来,有幸收获了一些朋友的认可,我很开心。
在上一篇文章中,我简单叙述了Dagger2这个库目前在Android开发中的一些短板,为什么我们学习Dagger-Android这个拓展库,以及如何使用这个拓展库。
今天我们进行代码分析,看看Dagger-Android是如何基于Dagger2实现一行代码实现所有同类组件依赖注入的。
阅读本文也许您需要准备的
本文可能需要您对Dagger2有一定的了解,包括它内部模板代码生成的一些逻辑。
核心代码
书承上文,我们知道,我们实现依赖注入的代码主要为以下两行:
public class MyApplication extends Application implements HasActivityInjector {
@Inject
DispatchingAndroidInjector dispatchingAndroidInjector;
@Override
public void onCreate() {
super.onCreate();
//1.Application级的依赖注入
DaggerMyAppComponent.create().inject(this);
}
@Override
public AndroidInjector activityInjector() {
return dispatchingAndroidInjector;
}
}
public class BaseActivity extends AppCompatActivity{
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
//2.Activity级的依赖注入
AndroidInjection.inject(this);
super.onCreate(savedInstanceState);
}
}
抛开这两行,也许我们还有更多疑问:
1.MyApplication中的dispatchingAndroidInjector成员是干嘛的
2.MyApplication实现的HasActivityInjector接口和实现的activityInjector()方法又是干嘛的
3.为什么这样2行依赖注入代码,就能代替之前我们每个Activity都需要写的模板代码呢:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// DO THIS FIRST. Otherwise frombulator might be null!
((SomeApplicationBaseType) getContext().getApplicationContext())
.getApplicationComponent()
.newActivityComponentBuilder()
.activity(this)
.build()
.inject(this);
// ... now you can write the exciting code
}
直接公布结论:
这里写图片描述
这里写图片描述
这三张图描述了很多东西,我们不需要先去看懂它,我们会随着我们的步骤,一步步分析透彻它,拨开云雾见晴天。、
首先我们分析Application中的这行代码:
DaggerMyAppComponent.create().inject(this);
一、DaggerMyAppComponent.create()原理
我们先点开create()方法,可以看到,无非是初始化了一个DaggerMyAppComponent对象,然后执行了initialize()方法
public static MyAppComponent create() {
return new Builder().build();
}
public static final class Builder {
private Builder() {
}
public MyAppComponent build() {
return new DaggerMyAppComponent(this);
}
}
private DaggerMyAppComponent(Builder builder) {
assert builder != null;
initialize(builder);
}
我们接着看initialize()方法:
private void initialize(final Builder builder) {
//1
this.mainActivitySubcomponentBuilderProvider =
new dagger.internal.Factory<
AllActivitysModule_ContributeMainActivitytInjector.MainActivitySubcomponent.Builder>() {
@Override
public AllActivitysModule_ContributeMainActivitytInjector.MainActivitySubcomponent.Builder
get() {
return new MainActivitySubcomponentBuilder();
}
};
this.bindAndroidInjectorFactoryProvider = (Provider) mainActivitySubcomponentBuilderProvider;
this.secondActivitySubcomponentBuilderProvider =
new dagger.internal.Factory<
AllActivitysModule_ContributeSecondActivityInjector.SecondActivitySubcomponent
.Builder>() {
@Override
public AllActivitysModule_ContributeSecondActivityInjector.SecondActivitySubcomponent
.Builder
get() {
return new SecondActivitySubcomponentBuilder();
}
};
this.bindAndroidInjectorFactoryProvider2 = (Provider) secondActivitySubcomponentBuilderProvider;
//2
this.mapOfClassOfAndProviderOfFactoryOfProvider =
MapProviderFactory
., AndroidInjector.Factory extends Activity>>builder(2)
.put(MainActivity.class, bindAndroidInjectorFactoryProvider)
.put(SecondActivity.class, bindAndroidInjectorFactoryProvider2)
.build();
//3
this.dispatchingAndroidInjectorProvider =
DispatchingAndroidInjector_Factory.create(mapOfClassOfAndProviderOfFactoryOfProvider);
//4
this.myApplicationMembersInjector =
MyApplication_MembersInjector.create(dispatchingAndroidInjectorProvider);
}
这就有点难受了,代码很多,我们一步步慢慢分析。
我们不要一次想着把这些代码彻底读懂,我们首先大概对整个流程有个了解,之后慢慢拆分代码不迟:
我们可以理解为直接初始化了MainActivitySubcomponentBuilder和SecondActivitySubcomponentBuilder的对象,这个对象能够提供一个对应ActivityComponent的实例化对象,有了这个实例化对象,我们就能够对对应的Activity进行依赖注入。
这个很明显了,把所有ActivityComponent的实例化对象都存储到一个Map中,然后这个Map通过放入mapOfClassOfAndProviderOfFactoryOfProvider对象中。
通过mapOfClassOfAndProviderOfFactoryOfProvider初始化dispatchingAndroidInjectorProvider对象
通过dispatchingAndroidInjectorProvider对象初始化myApplicationMembersInjector对象
好的基本差不多了 我们看看每个步骤都是如何实现的
第1步详细分析
以SecondActivity的这行代码为例:
this.secondActivitySubcomponentBuilderProvider =
new dagger.internal.Factory< //1.看这行,实际上是new了一个能提供SecondActivitySubcomponentBuilder()的Provider
AllActivitysModule_ContributeSecondActivityInjector.SecondActivitySubcomponent
.Builder>() {
@Override
public AllActivitysModule_ContributeSecondActivityInjector.SecondActivitySubcomponent
.Builder
get() {
//2.这个SecondActivitySubcomponentBuilder能干什么呢
return new SecondActivitySubcomponentBuilder();
}
};
private final class SecondActivitySubcomponentImpl
implements AllActivitysModule_ContributeSecondActivityInjector.SecondActivitySubcomponent {
private MembersInjector secondActivityMembersInjector;
//3.我们点开构造方法,看到实际是走了initialize(builder);
private SecondActivitySubcomponentImpl(SecondActivitySubcomponentBuilder builder) {
assert builder != null;
initialize(builder);
}
@SuppressWarnings("unchecked")
private void initialize(final SecondActivitySubcomponentBuilder builder) {
//4.实际上是初始化了一个SecondActivity_MembersInjector,这个Injector能够对SecondActivity所需要的对象提供注入
this.secondActivityMembersInjector =
SecondActivity_MembersInjector.create(SecondActivityModule_ProvideNameFactory.create());
}
@Override
public void inject(SecondActivity arg0) {
//5.我们不难想象,不久后当SecondActivity需要依赖注入,一定会执行这行代码进行对象注入
secondActivityMembersInjector.injectMembers(arg0);
}
}
看到这里我们明白了,实际上第一步是ApplicationComponent实例化了所有的ActivityComponent(就是那个能提供SecondActivitySubcomponentBuilder()的Provider)
然后每个ActivityComponent都能提供某个Activity依赖注入所需要的ActivityMembersInjector。
第2步第3步分析
第2步就很简单了,这些ActivityComponent都被放入了一个Map集合中,该集合又放入了apOfClassOfAndProviderOfFactoryOfProvider中,这个Provider实际上也是一个工厂,负责提供该Map的实例化
第3步也很好理解,我们MapProvider工厂交给了就是dispatchingAndroidInjectorProvider去管理。
第4步分析:
实际上我们传入dispatchingAndroidInjectorProvider做了什么呢?
我们看看MyApplication_MembersInjector对象是干嘛的:
//核心代码
public final class MyApplication_MembersInjector implements MembersInjector {
private final Provider> dispatchingAndroidInjectorProvider;
...
...
...
//依赖注入Application!
@Override
public void injectMembers(MyApplication instance) {
instance.dispatchingAndroidInjector = dispatchingAndroidInjectorProvider.get();
}
}
大家可以明白了,原来第四步初始化该对象时,会将传入的dispatchingAndroidInjectorProvider存储起来,将来用到的时候将其对象注入到需要注入的Application中:
public class MyApplication extends Application implements HasActivityInjector {
//就是注入给这个成员变量!
@Inject
DispatchingAndroidInjector dispatchingAndroidInjector;
//省略其他代码
...
...
}
整理思路
现在我们再来看一下这张图,相信您已经对这张图有所领会了。
这里写图片描述
可以看到,Application进行初始化时,仅仅一部DaggerMyAppComponent.create(),就已经处理了如此多的事件,初始化了这么多工厂类,等待我们去调用他们实现依赖注入了。
二、DaggerMyAppComponent.create().inject(this)原理
其实这个步骤就是确定一下我们上面的对Dagger-Android这个库的分析是否是对的,我们来看这行代码
public final class DaggerMyAppComponent implements MyAppComponent {
...
...
...
@Override
public void inject(MyApplication application) {
myApplicationMembersInjector.injectMembers(application);
}
}
这就和我们上面第四步的分析吻合了:
//我们刚才分析过的,再看一遍
//核心代码
public final class MyApplication_MembersInjector implements MembersInjector {
private final Provider> dispatchingAndroidInjectorProvider;
...
...
...
//依赖注入Application!
@Override
public void injectMembers(MyApplication instance) {
instance.dispatchingAndroidInjector = dispatchingAndroidInjectorProvider.get();
}
}
public class MyApplication extends Application implements HasActivityInjector {
//就是注入给这个成员变量!
@Inject
DispatchingAndroidInjector dispatchingAndroidInjector;
//省略其他代码
...
...
}
整理思路
这里写图片描述
可以看到,这一步实际上我们做了至关重要的一步,就是把Application中的这个不知道是干什么的成员变量进行了初始化!!!
@Inject
DispatchingAndroidInjector dispatchingAndroidInjector;
我们现在知道,这个dispatchingAndroidInjector中,实际拥有一个Map,Map中有着所有Activity所需依赖注入使用的Component!
可以说,这个看起来平凡无奇的成员变量,才是我们整个项目依赖注入的大管家!
顿悟
相信如果您认真一步步看到这里,对于下面的2个问题,您已经有了自己的答案:
1.MyApplication中的dispatchingAndroidInjector成员是干嘛的
三、 AndroidInjection.inject(this)原理
我们在初始化一个Activity,必然会调用BaseActivity中的这行代码:
AndroidInjection.inject(this)
我们好奇,为什么仅仅在BaseActivity这样1行依赖注入代码,就能代替之前我们每个Activity都需要写的模板代码呢?
答案近在眼前。
public final class AndroidInjection {
...
...
...
public static void inject(Activity activity) {
//核心代码如下
//1.获取Application
Application application = activity.getApplication();
//2.通过activityInjector()获取dispatchingAndroidInjector对象!
AndroidInjector activityInjector =
((HasActivityInjector) application).activityInjector();
//3.dispatchingAndroidInjector依赖注入
activityInjector.inject(activity);
}
}
前两步毫无技术含量,我们继续看activityInjector.inject(activity):
我们需要找到真正的activityInjector对象,就是DispatchingAndroidInjector:
public final class DispatchingAndroidInjector implements AndroidInjector {
@Override
public void inject(T instance) { //instance在这里为Activity
//1.执行maybeInject()方法
boolean wasInjected = maybeInject(instance);
}
public boolean maybeInject(T instance) { //instance在这里为Activity
//2.获取对应Provider
Provider> factoryProvider =
injectorFactories.get(instance.getClass());
AndroidInjector.Factory factory = (AndroidInjector.Factory) factoryProvider.get();
//3.获取对应的ActivityMembersInjector
AndroidInjector injector =
factory.getClass().getCanonicalName());
//4.注入到对应的Activity中
injector.inject(instance);
}
}
整理思路
可以看到,这一步实际上我们只是取得Application中的大管家dispatchingAndroidInjector,通过它取得了对应Activity的Inject实例,并进行依赖注入。
顿悟
相信如果您认真一步步看到这里,对于下面的2个问题,您已经有了自己的答案:
2.MyApplication实现的HasActivityInjector接口和实现的activityInjector()方法又是干嘛的
3.为什么这样2行依赖注入代码,就能代替之前我们每个Activity都需要写的模板代码呢:
至此,AndroidInject原理分析基本也到了尾声
附录
最后提供一下本文demo源码连接和图片资源,都已放到Github:
android dagger2 讲解,告别Dagger2模板代码:DaggerAndroid原理解析相关推荐
- Android代码入侵原理解析(一)
Original 2017-05-06 付超红 滴滴安全应急响应中心 2017年初,在滴滴安全沙龙上,滴滴出行安全专家--付超红,针对App的攻与防进行了分享.会后大家对这个议题反响热烈,纷纷求详情求 ...
- Android应用市场省流量更新(增量升级)原理解析
一.前言 最近在看热修复相关的框架,之前我们已经看过了阿里的Dexposed和AndFix这两个框架了,不了解的同学可以点击这里进行查看:Dexposed框架原理解析 和 AndFix热修复框架原理解 ...
- Android支付宝蚂蚁森林能量自动收取插件开发原理解析
转发一篇高技术含量的文章,原文网址为:https://www.52pojie.cn/thread-794312-1-1.html 一.前言 关于支付宝的蚂蚁森林能量收取这个非常有重大意义的东西,本人表 ...
- JS 实现2+2=5的代码 实现原理解析
当我在http://segmentfault.com/q/1010000000531302 看到的时候 先是一惊. 这是代码 g = function () { H = 3 return H ...
- yolov5代码及原理详解
yolov5代码及原理解析 文章目录 yolov5代码及原理解析 一.代码及原理解析 1.输入端 (1) letterbox (2) Mosaic增强 (3) anchor 1)关闭时 2)开启时 2 ...
- Android 代码混淆语法讲解及常用模板(转)
转载请注明原博客地址 Android 代码混淆语法讲解及常用模板 前言 混淆对于每一个开发者来说都不陌生,对于大多数 APP 而言,在上线之前,通常会进行代码混淆,加固,防止自己的 APP 被别人轻 ...
- 将Android进行到底之Dagger2(一)
系列文章目录 将Android进行到底之Dagger2(二) 将Android进行到底之Dagger2(三) 文章目录 系列文章目录 前言 一.什么是依赖注入? 二.IOC与Dagger2 1.IOC ...
- Android 依赖注入框架 Dagger2使用
前言 Dagger 2这个匕首确实很难上手,上手后又比较难瞬间掌握,可以这么说,刚开始使用就是用来尝(zhuang)鲜(X)的,但相信随着使用的加深,会不断体会到它对于整个项目架构的极强辅助作用,能使 ...
- dagger android,在Android开发中使用Dagger2的方法
在Android开发中使用Dagger2的方法 发布时间:2020-12-08 17:12:38 来源:亿速云 阅读:236 作者:Leah 在Android开发中使用Dagger2的方法?相信很多没 ...
最新文章
- 封装echarts china map geo实现dispatch触发geoSelect事件高亮显示某个省份和城市,并定义复杂样式
- 如何在Zynq-7000上烧写PL Image
- Java生成Word文档
- DiscuzX2.5视频教程
- 纽约时报:安全问题将毁掉整个互联网
- 抓取AJAX网页的方法-Firefox组件,C#集成
- ZeroMQ实例-使用ZMQ(ZeroMQ)进行局域网内网络通信
- NDoc使用简要手册的补充
- java复习系列[1] - Java 基础
- jzoj3771. 【NOI2015模拟8.15】小 Z 的烦恼
- js判断浏览器,包括Edge浏览器
- 购物中心弱电智能化系统工程施工方案
- 低通滤波器转带通滤波器公式由来_什么是-3dB截止频率?浅析滤波器原理、分类和滤波器优化!...
- MATLAB的WFDB软件下载及使用
- VC6.0的兼容性问题解决方案
- 树莓派4B修复双触摸屏触摸问题
- cortex m3 开源_开源增强现实耳机,Steam的125M有效帐户等
- linux上的客户端连接window上的服务器
- 携手漫威超级英雄,华米科技开启智能穿戴新时代
- 全球及中国多晶透明陶瓷行业供需及竞争形势分析报告2021~2026年