听说Dagger2和Retrolambda很久了,本来是拒绝的,觉得只是锦上填一点小花而已,但最近看来,Github上已经有很多开源项目采用,再不学就又落后面了……
看完下面这三篇就差不多了,其他很多都是重复的,Dagger2是唯一的我感觉看完官方的讲解还无从下手
http://blog.fidroid.com/post/android/dagger-on-android-dagger2xiang-jie
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0519/2892.html
再配合我fork过来的一个例子,我正在做完善,原作者是做示例Dagger2 + RxJava + MVP, 我打算做成完善的
一般的使用和原理就齐活了~
Dagger2的使用配置:在build.gradle
apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
}
}
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {
applicationId "com.huxian"
minSdkVersion 19
targetSdkVersion 23
versionCode 1
versionName "1.0"
renderscriptTargetApi 19
renderscriptSupportModeEnabled false
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
apt 'com.google.dagger:dagger-compiler:2.0'
compile 'javax.annotation:jsr250-api:1.0'
compile 'com.google.dagger:dagger:2.0'
}
下面是我理解的用法,一个用过Spring IoC的Android开发工程师
Spring IoC用起来非常好上手
提供依赖的,用@Component注解,需要依赖的地方 用@Autowired注解,配置文件加上component-scan就差不多了。
因为接口可能有多个实现,也有@qualifier提供过滤
实现是依赖反射,涉及动态生成类
Dagger2感觉并不太好上手
提供依赖的类用@Module注解
能提供的依赖用@Provide注解,(这是因为给第三方提供依赖用的,自己的类提供依赖,只需要在构造函数上加上@Inject即可)
需要依赖的地方 用@Inject注解,
最终要靠手动调用inject方法完成依赖的注入,这个inject方法要在@Compoent的类里提供。
Dagger2为了性能考虑,没有使用反射,注解是编译时处理。
另外Spring提供的默认单例实现貌似只能是应用级的单例,而Dagger2提供了Scope的概念,可以配合声明周期使用,分成应用级,Activity级等
上面的博客说的最清楚的还是 https://github.com/konmik/konmik.github.io/wiki/Snorkeling-with-Dagger-2
尤其是building完后,对照build/generated/sources/apt/下生成的文件加断点,才能理解好整个过程
采用MVP开发模式时,需要在Activity或Fragment里诸如Presenter,看上面注明的Comedy工程
@Inject MovieDetailPresenter movieDetailPresenter;
这种写法movieDetailPresenter在调用inject是已经生成,如果想在使用时才生成对象有两种办法
一种是使用Lazy< MovieDetailPresenter >
一种按照后来我改写的, ActorDetailActivity 里不再是通过@Inject方式提供movieDetailPresenter,而是改由在ActorDetailComponent里声明
ActorDetailPresenter actorDetailPresenter();方法提供.
这样可以实现在调用actorDetailPresenter时才生成对象。这种情况可以应用在ViewPager里Framgent可见时才去获取,进而发网络请求
注意:ActorDetailPresenter actorDetailPresenter();这里方法名字不重要,重要的还是返回值。编译时,需要让编译期能生成构造出ActorDetailPresenter 对象的方法。这个也有两种办法:
一种是在ActorDetailPresenter 的构造函数声明@inject,告诉编译器需要ActorDetailPresenter 对象时从这里构造就可以
一种是在Module里以@Provide的形式提供。
@Provides
@ActivityScope
ActorDetailPresenter provideActorDetailPresenter(GetActorDetailUsecase getActorDetailUsecase){
return new ActorDetailPresenter(getActorDetailUsecase);
}
如果这两个都没写呢,编译时会有提示:
com.huxian.presenter.ActorDetailPresenter cannot be provided without an @Inject constructor or from an @Provides-annotated method.
提示说的很清楚
再说一下Angualr 1.x里的依赖注入,同样是Google家搞出来的东西,它的使用更简单一些。
简单说,就是在Controller依赖Service,而Service提供了三种方法定义,这里的定义也就是告诉了Angualr框架该怎么构造出这些可以被依赖的对象。在Controller里呢,简洁写法只需要在对应function里的入参写上Service名字就OK了~