Dagger2解惑
最近一直在关注Android项目开发中的整体架构设计问题,如何在复杂的业务逻辑和日益膨胀的功能需求面前保持项目架构的稳定是一个很值得深入学习的问题。前段时间看到开发社区里有不少人在推崇Dagger2 + MVP模式来构建整体项目框架,MVP模式之前在项目中有使用过,MVP虽然从Activity和Fragment中抽离出了业务逻辑层,但是也不能完全解耦代码。
而Dagger2的出现正好解决了这一问题,这里不谈Dagger2的使用方法,主要是分享下Dagger2的工作原理和使用中遇到的一些疑惑。
Dagger2的工作原理
用过Dagger2的同学都知道,只要通过几个注解、Component、Module就可以实现依赖注入,再也不用写new
了,简直太神奇了。下面就让我们揭开Dagger2神秘的面纱,看看它到底是怎么工作的
|
|
|
|
|
|
上面代码主要有三部分组成,ApplicationComponent、ApplicationModule、DataManager(ApiService是其中一个成员变量)
在编译时,Dagger2会自动生成ApplicationComponent
实例类DaggerApplicationComponent
,如下
|
|
从上面的代码可以看出ApplicationComponent
构建了一系列Provider
,而这些Provider
最后在对象注入时使用的,来看下一下代码
|
|
|
|
|
|
ActivityComponet
是依赖于ApplicationComponent
,所以它可以获得ApplicationComponent
构建的一系列Provider,MainActivity
是需要注入的对象,最终MainActivity.mDataManager
变量会被注入赋值
|
|
Dagger2的那些坑
分析完Dagger2的工作原理后,让我们来看看在实际使用过程中会遇到哪些坑
component 的 inject 函数不要声明基类参数
如MainActivity
和SettingActivity
都是继承于BaseActivity
,那么在注入时只能指定MainActivity
和SettingActivity
,而不能想当然的使用基类BaseActivity
,这样子类是不会被注入的。这样就会带来一个问题,如果说我们很多的Activity都需要注入,那么在ActivityComponet
中我就需要这么写(是不是很蛋疼 ~_~!!!)12345678void inject(MainActivity activity);void inject(LoginActivity activity);void inject(RegisterActivity activity);void inject(AccountAuthActivity activity);void inject(UserInfoEditActivity activity);void inject(UserStatusActivity activity);void inject(UserBindRescuerActivity activity);......Scope 注解必须用在 module 的 provide 方法上,否则并不能达到局部单例的效果
如果 module 的 provide 方法使用了 scope 注解,那么 component 就必须使用同一个注解,否则编译会失败
如果 module 的 provide 方法没有使用 scope 注解,那么 component 和 module 是否加注解都无关紧要,可以通过编译,但是没有局部单例效果;
对于直接使用 @Inject 构造函数的依赖,如果把 scope 注解放到它的类上,而不是构造函数上,就能达到局部单例的效果了;
总结
至此,Dagger2的整个注入流程我们就分析完了,其实也不算复杂,只是使用了大量的设计模式,分析代码时跳来跳去的容易把人搞晕。Dagger2的出现是解耦了代码,但是同时也带来了其它的一些问题,比如:引入大量Component后期管理、维护就很非常困难,Component划分粒度问题,当业务逻辑存在重复或者相似性时如何重用Component等等,这些都是需要进一步学习和思考。
欢迎大家拍砖
原创不易,欢迎转载,但还请注明出处:waynell.github.io