本文适合有一定的Dagger2使用基础的同学

前两篇文章我们讲了两种多模块项目怎么使用Dagger2。

发现在每个Activity的onCreate中都需要调一个inject方法NewsComponentHolder.newsComponent.inject(this)

UserComponentHolder.userComponent.inject(this)

其实还可以用dagger2专给android使用的dagger.android来简化这种操作。

先看普通多模块项目

dagger.android的核心思想是在每个Component收集两个MapMap, Provider>> injectorFactoriesWithClassKeys

Map>> injectorFactoriesWithStringKeys

这两个Map定义在AndroidInjectionModule中@Beta

@Module

public abstract class AndroidInjectionModule {

@Multibinds

abstract Map, AndroidInjector.Factory>> classKeyedInjectorFactories();

@Multibinds

abstract Map> stringKeyedInjectorFactories();

private AndroidInjectionModule() {}

}

dagger.android会把把收集到的这两个Map注入到DispatchingAndroidInjector中,dagger.android就是通过这个DispatchingAndroidInjector注入到Activity,Fragment中

怎么收集呢

首先定义一个 xxxBindModule ,将要注入的Activity,fragment用@ContributesAndroidInjector注解

dagger.android会把这些收集到前面的Map中去@Module(includes = [AndroidInjectionModule::class])

abstract class NewsBindModule {

@ContributesAndroidInjector

abstract fun newsActivity(): NewsActivity

}

然后相应的Component的modules加上xxxBindModule,

去掉inject(XXXActivity)这样的一大堆声明方法,干净多了@NewsScope

@Subcomponent(modules = [NewsModule::class, NewsBindModule::class])

interface NewsComponent {

@Subcomponent.Factory

interface Factory {

fun create(): NewsComponent

}

}

之后按照dagger.android用法要让Application实现HasAndroidInjector接口,并注入dispatchingAndroidInjector实例class AppApplication : BaseApplication(), NewsComponentProvider, UserComponentProvider, HasAndroidInjector {

@Inject

lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector

lateinit var appComponent: AppComponent

override fun onCreate() {

super.onCreate()

appComponent = DaggerAppComponent.factory().create(this)

}

override fun provideNewsComponent(): NewsComponent {

return appComponent.newsComponentFactory().create()

}

override fun provideUserComponent(): UserComponent {

return appComponent.userComponentFactory().create()

}

override fun androidInjector(): AndroidInjector {

return dispatchingAndroidInjector

}

}

再在Component加上一个注入到上面Appliction的方法(因为news模块拿不到AppApplication的引用,直接注入到Any好了)@NewsScope

@Subcomponent(modules = [NewsModule::class, NewsBindModule::class])

interface NewsComponent {

@Subcomponent.Factory

interface Factory {

fun create(): NewsComponent

}

fun inject(any: Any)

}

然后在AppApplication中注入class AppApplication : BaseApplication(), NewsComponentProvider, UserComponentProvider {

@Inject

lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector

lateinit var appComponent: AppComponent

override fun onCreate() {

super.onCreate()

appComponent = DaggerAppComponent.factory().create(this)

NewsComponentHolder.newsComponent.inject(this)

}

override fun provideNewsComponent(): NewsComponent {

return appComponent.newsComponentFactory().create()

}

override fun provideUserComponent(): UserComponent {

return appComponent.userComponentFactory().create()

}

override fun androidInjector(): AndroidInjector {

return dispatchingAndroidInjector

}

}

最后在Activity,fragment的onCreate方法中加入AndroidInjection.inject(this),注意要放在super.onCreate(savedInstanceState)前面,我们把这一步放在BaseActivity,BaseFragment里open class BaseActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {

AndroidInjection.inject(this)

super.onCreate(savedInstanceState)

}

}

然后Activity只要继承BaseActivity就可以了,不需要写任何注入代码了,像平时使用一样了,想要注入对象的变量加 @Inject就可以了class NewsActivity : BaseActivity() {

@Inject

lateinit var set: Set

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(R.layout.activity_news)

text.text = set.toString()

}

}

这种写法对于单模块项目没有问题,但是对多模块项目来说这有问题了,上面我们只注入了news模块的,user模块的没有。我们有多个Component,但是这里只有一个dispatchingAndroidInjector,你用哪个Component注入都不全,后面注入的会覆盖前面注入的。所以这里要改造下

从前面我们知道一个Component最终生成一个DispatchingAndroidInjector,多个Component我们把它们都收集起来

我们先定义一个BaseDispatchingInjector,它相当于前面的AppApplication,接收一个Component注入的DispatchingAndroidInjectorclass BaseDispatchingInjector {

@Inject

lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector

}

然后把每个Component里的inject(any: Any)改成inject(baseDispatchingInjector: BaseDispatchingInjector)@NewsScope

@Subcomponent(modules = [NewsModule::class, NewsBindModule::class])

interface NewsComponent {

@Subcomponent.Factory

interface Factory {

fun create(): NewsComponent

}

fun inject(baseDispatchingInjector: BaseDispatchingInjector)

}

@UserScope

@Subcomponent(modules = [UserModule::class, UserBindModule::class])

interface UserComponent {

@Subcomponent.Factory

interface Factory {

fun create(): UserComponent

}

fun inject(baseDispatchingInjector: BaseDispatchingInjector)

}

这样注入val userDispatchingInjector = BaseDispatchingInjector()

UserComponentHolder.userComponent.inject(userDispatchingInjector)

val newsDispatchingInjector = BaseDispatchingInjector()

NewsComponentHolder.newsComponent.inject(newsDispatchingInjector)

这样我们每个模块都得到一个BaseDispatchingInjector,并且里面每个Activity,Fragment对应的Map都注入好了

然后就要定义一个MultiModuleAndroidInjector把每个模块的BaseDispatchingInjector整合到一起成为一个单独的AndroidInjectorclass MultiModuleAndroidInjector : AndroidInjector {

private val injectors = mutableListOf()

fun addInjector(injector: HasDispatchingInjector) {

injectors.add(injector)

}

override fun inject(instance: Any) {

val wasInjected = injectors.any { it.dispatchingAndroidInjector.maybeInject(instance) }

if (!wasInjected) {

throw IllegalArgumentException("injection failed")

}

}

}

这个MultiModuleAndroidInjector在注入的时候会每个BaseDispatchingInjector都去尝试看能不能注入,这样就把所有Component的注解都遍历了

看AppApplication最后实现class AppApplication : BaseApplication(), NewsComponentProvider, UserComponentProvider,

HasAndroidInjector {

lateinit var appComponent: AppComponent

private val multiModuleAndroidInjector = MultiModuleAndroidInjector()

override fun onCreate() {

super.onCreate()

appComponent = DaggerAppComponent.factory().create(this)

val userDispatchingInjector = BaseDispatchingInjector()

UserComponentHolder.userComponent.inject(userDispatchingInjector)

multiModuleAndroidInjector.addInjector(userDispatchingInjector)

val newsDispatchingInjector = BaseDispatchingInjector()

NewsComponentHolder.newsComponent.inject(newsDispatchingInjector)

multiModuleAndroidInjector.addInjector(newsDispatchingInjector)

}

override fun provideNewsComponent(): NewsComponent {

return appComponent.newsComponentFactory().create()

}

override fun provideUserComponent(): UserComponent {

return appComponent.userComponentFactory().create()

}

override fun androidInjector(): AndroidInjector {

return multiModuleAndroidInjector

}

}

dagger android,dagger.android多模块项目实现相关推荐

  1. android dagger2 懒加载,Android Dagger依赖注入框架浅析

    今天接触了Dagger这套android的依赖注入框架(DI框架),感觉跟Spring 的IOC差不多吧.这个框架它的好处是它没有采用反射技术(Spring是用反射的),而是用预编译技术,因为基于反射 ...

  2. android项目模块导入eclipse编译报错,android中studio导入eclipse项目报错怎么办

    android中studio导入eclipse项目报错怎么办 发布时间:2020-07-15 17:34:45 来源:亿速云 阅读:96 作者:清晨 这篇文章将为大家详细讲解有关android中stu ...

  3. Android github上优秀开源项目分类汇总

    第一部分 个性化控件(View) 主要介绍那些不错个性化的 View,包括 ListView.ActionBar.Menu.ViewPager.Gallery.GridView.ImageView.P ...

  4. 【Android】Android开源项目分类汇总

    第一部分 个性化控件(View) 主要介绍那些不错个性化的View,包括ListView.ActionBar.Menu.ViewPager.Gallery.GridView.ImageView.Pro ...

  5. [转]Android github上优秀开源项目分类汇总

    第一部分 个性化控件(View) 主要介绍那些不错个性化的 View,包括 ListView.ActionBar.Menu.ViewPager.Gallery.GridView.ImageView.P ...

  6. 2017 Android github上优秀开源项目分类汇总

    第一部分 个性化控件(View) 主要介绍那些不错个性化的 View,包括 ListView.ActionBar.Menu.ViewPager.Gallery.GridView.ImageView.P ...

  7. android studio项目总结,android studio 3.0 升级 项目遇到的问题及更改思路(问题小结)...

    Android Studio从3.0版本新增了许多功能,当然首当其冲就是从3.0版本新增了对 Kotlin 开发语言的支持,除此之外还有其他一些新功能,例如:Android Profiler (其中包 ...

  8. 十一、Android学习第十天——项目开始(转)

    (转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 十一.Android学习第十天--项目开始 Android知识点的学习告一 ...

  9. Android开发之ApiCloud模块开发之模块引用第三方库的问题

    因为现在第三方库比较多,所以很多人为了快速开发导致库用烂大街了,但是在模块开发中本人不建议使用第三方库的依赖会有很多问题,要么是资源图片找不到,要么是布局找不到啥的,但是有的需求只有第三方库怎么办呢? ...

最新文章

  1. A、B、C、D、E类IP地址都是怎么划分的?
  2. java-并发-并发容器(3)
  3. IBOOKS导入EPUB出现-23错误时解决方法
  4. 《Python Cookbook 3rd》笔记(1.4):查找最大或最小的N个元素
  5. FreeRTOS如何结束和重新启动调度程序
  6. 2020年领导最满意的可视化工具!分分钟做好数据报表,吊打python
  7. 增程式串联混合动力实际项目模型,本模型基于Cruise软件和Simulink软件共同搭建完成,并实际应用,本资料包包含所有源文件
  8. VOC2007-2012数据集
  9. Android - Enable fullscreen mode
  10. java基于uni-app框架的民宿客房预订系统 小程序
  11. 004_Makefile的编译
  12. 适合中小型企业的OA系统网上试用整理
  13. hp-unix操作系统root账号被锁定的两种解决方法:
  14. 手把手教你安装nvidia显卡驱动
  15. 酷炫!可视化神器Plotly玩转饼图
  16. Docker自定义镜像上传阿里云
  17. poj 3975hdu 1850 (nim)
  18. 植物叶片——丙二醛MDA
  19. 程序员业余项目死亡的原因
  20. 给排水计算机应用电子版,给排水规范大全

热门文章

  1. HDU 1080 Human Gene Functions
  2. 敏捷结果30天之第六天:周五回顾,找到三件做的好以及三件需要改善的事情...
  3. 选择DataGrid中的CheckBox控件后该行背景变色
  4. mysql 上一条 下一条,MYSQL实现上一条下一条功能
  5. 地脚螺钉直径系列_百科:螺栓、螺钉、螺丝三个概念,别再傻傻分不清!
  6. 凡科虚拟服务器怎样做301,虚拟主机301重定向怎么做?网站301重定向方法之一
  7. kafka partition分配_kafka的分区分配策略
  8. 代码管理规范_微服务架构下代码管理规范
  9. 单片机节日彩灯实训报告_单片机课程设计(节日彩灯控制)
  10. 四路服务器芯片组,四路服务器主板配置