1.导入Dagger2
project的build.gradle中
buildscript {
....
dependencies {
classpath 'com.android.tools.build:gradle:2.1.0'
// 添加android-apt 插件
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
}
app的build.gradle中
apply plugin: 'com.android.application'
// 应用插件
apply plugin: 'com.neenbedankt.android-apt'
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {
applicationId "com.mahao.alex.architecture"
minSdkVersion 15
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.3.0'
// dagger 2 的配置
compile 'com.google.dagger:dagger:2.4'
apt 'com.google.dagger:dagger-compiler:2.4'
compile 'org.glassfish:javax.annotation:10.0-b28'// 添加java 注解库
}
android-apt是Gradle编译器的插件,主要两个作用:
2.Dagger2 API
public @interface Component {
Class>[] modules() default {};
Class>[] dependencies() default {};
}
public @interface Subcomponent {
Class>[] modules() default {};
}
public @interface Module {
Class>[] includes() default {};
}
public @interface Provides {
}
public @interface MapKey {
boolean unwrapValue() default true;
}
public interface Lazy {
T get();
}
用在dagger2中的 JSR-330(Java中的依赖注入标准)定义的注解
public @interface Inject {
}
public @interface Scope {
}
public @interface Qualifier {
}
3.dagger2 使用
3.1 @inject使用
http://blog.csdn.net/lisdye2/article/details/51942511
方式一:由module中@Provides 注解的providerXXX()提供对象
public class Person {
person(){
}
}
@Module //依赖对象提供者
public class ActivityModule{
private SplashActivity activity;
public ActivityModule(SplashActivity activity) {
this.activity = activity;
}
@Provides // 关键字,标记具体提供依赖对象的方法
SplashActivity providerSplashActivity (){
return activity;
}
@Provides // 关键字,标记具体提供依赖对象的方法
Person providerPerson(){
return new Person();
}
}
@Component(modules = ActivityModule.class)
public interface ActivityComponent {
void inject(SplashActivity splashActivity );
}
到这重新build项目, AndroidStudio -> Build -> Make Project,生成
DaggerXXXComponent。
public class SplashActivity extends AppCompatActivity {
@Inject
Person person;
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
//开始注入
DaggerActivityComponent.builder()
.ActivityModule(new ActivityModule())
.build()
.inject(this);
}
}
方式二:@Inject注解类(Person )的构造函数,直接初始化对象
public class Person {
@inject //@Inject注解构造函数
person(){
}
}
@Module //依赖对象提供者
public class ActivityModule{
private SplashActivity activity;
public ActivityModule(SplashActivity activity) {
this.activity = activity;
}
@Provides // 关键字,标记具体提供依赖对象的方法
SplashActivity providerSplashActivity (){
return activity;
}
}
//记得先rebuild 项目
public class SplashActivity extends AppCompatActivity {
@Inject
Person person;
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
//开始注入
DaggerActivityComponent.builder()
.ActivityModule(new ActivityModule())
.build()
.inject(this);
}
}
需要参数的实例化对象
public class Person {
String name;
person(String name){
this.name=name;
}
}
ActivityModule:
@Module //依赖对象提供者
public class ActivityModule{
private SplashActivity activity;
public ActivityModule(SplashActivity activity) {
this.activity = activity;
}
@Provides // 关键字,标记具体提供依赖对象的方法
SplashActivity providerSplashActivity (){
return activity;
}
@Provides // name由ActivityModule中providerString提供
Person providerPerson(String name){
return new Person(name);
}
@Provides // 关键字,标记具体提供依赖对象的方法
String providerString(){
return "李好";
}
}
//记得先rebuild 项目
public class SplashActivity extends AppCompatActivity {
@Inject
Person person;
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
//开始注入
DaggerActivityComponent.builder()
.ActivityModule(new ActivityModule())
.build()
.inject(this);
}
}
注入流程
步骤1:查找Module中是否存在提供对象(@Inject标记的对象)的方法。
步骤2:若Module中存在提供该对象的方法(providerXXX),查看该方法是否有参数
步骤2.1:若有参数,则按从步骤1开始依次初始化每个参数(即从(Module的providerXXX)中获取参数值)。
步骤2.2:若没有参数,则直接调用初始化该类实例,一次依赖注入结束。
步骤3:若Module中没有提供该对象方法,则查找@Inject注解的构造函数,看构造函数是否有参数
步骤3.1:若有参数,则从步骤1开始依次初始化每个参数
步骤3.2:若没有参数,则直接初始化该类实例,一次依赖注入结束。
3.2 @Qualifier
使用场景:
当一个类有两个构造函数时,使用Dagger2时,如何获取指定构造函数new出来的对象 ? 这就需要@Qualifier来解决。
public class Person {
String name;
person(){
}
person(String name){
this.name=name;
}
}
首先
用@Qualifier 自定义一个限定符
@Qualifier//限定符
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Type {
String value() default "";//默认值为""
}
修改ActivityModule, 添加@Named;
@Module //依赖对象提供者
public class ActivityModule{
private SplashActivity activity;
public ActivityModule(SplashActivity activity) {
this.activity = activity;
}
@Provides // 关键字,标记具体提供依赖对象的方法
SplashActivity providerSplashActivity (){
return activity;
}
@Named("normal")
@Provides // 关键字,标记具体提供依赖对象的方法
Person providerPerson(String name){
return new Person(name);
}
@Named("default")
@Provides // 关键字,标记具体提供依赖对象的方法
Person providerPerson(){
return new Person();
}
@Provides
public String provideString(){
return new String(“有参数”);
}
}
修改SplashActivity , 添加@Type;
public class SplashActivity extends AppCompatActivity {
@Named("default")
@Inject
Person person;
@Named("normal")
@Inject
Person person2;
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
//开始注入
DaggerActivityComponent.builder()
.ActivityModule(new ActivityModule())
.build()
.inject(this);
Log.i("dagger","person.name = "+ person.name+"; person2.name = "+ person2.name);
}
}
打印结果
person.name = null; person2.name=“有参数”
此时的person,person2是由不同的构造方法创建。
通过字符串标记一个对象,容易导致前后不匹配.做如下修改
@Qualifier // 关键词
@Retention(RetentionPolicy.RUNTIME) // 运行时仍可用
public @interface PersonForDefault {
}
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface PersonForName {
// name 对象的注解
}
**********************ActivityModule**********************
@PersonForDefault
@Provides // 关键字,标记具体提供依赖对象的方法
Person providerPerson(String name){
return new Person(name);
}
@PersonForName
@Provides // 关键字,标记具体提供依赖对象的方法
Person providerPerson(){
return new Person();
}
@Provides
public String provideString(){
return new String(“有参数”);
}
********************SplashActivity*************************
@PersonForDefault
@Inject
Person person;
@PersonForName
@Inject
Person person2;
3.3 @Singleton
@Singleton注解实际上实现的是一个全局单例模式,通过@Singleton创建出来的全局单例并不保持在静态域上,而是保留在Component实例中。不同的Component实例对象通过@Singleton创建出来的全局单例不同。
public class SplashActivity extends AppCompatActivity{
@Inject
Person person;
@Inject
Person person2;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 构造桥梁对象
ActivityComponent splashcomponent= DaggerActivityComponent.builder()
.ActivityModule(new ActivityModule())
.build();
//注入
component.inject(this);
// 打印两个对象的地址
Log.i("dagger","person = "+ person.toString()+"; person2 = "+ person2.toString());
}
}
打印结果
person = com.nihao.dagger2.Person@430d1620;
person2 = com.nihao.dagger2.Person@430d17c8;
person 和person2 地址不相等,不是同一个对象,即创建了2个对象。
修改ActivityModule代码,在providerPerson()上添加 @Singleton注解
@Module //依赖对象提供者
public class ActivityModule{
private SplashActivity activity;
public ActivityModule(SplashActivity activity) {
this.activity = activity;
}
@Provides // 关键字,标记具体提供依赖对象的方法
SplashActivity providerSplashActivity (){
return activity;
}
@Singleton
@Provides // 关键字,标记具体提供依赖对象的方法
Person providerPerson(){
return new Person();
}
}
ActivityComponent 也要添加@Singleton,否则无法编译
@Singleton
@Component(modules = ActivityModule.class)
public interface ActivityComponent {
void inject(SplashActivity splashActivity );
}
重新运行
person = com.mahao.alex.architecture.dagger2.Person@4310f898; person2= com.mahao.alex.architecture.dagger2.Person@4310f898;
person 和person2 地址相等,是由splashcomponent提供同一个对象。
**********************修改ActivityComponent **************
@Singleton
@Component(modules = ActivityModule.class)
public interface ActivityComponent {
void inject(SplashActivity splashActivity );
void inject(MainActivity mainActivity );
}
*******************ActivityModule添加***********************
MainActivity mainactivity;
public ActivityModule(MainActivity mainactivity) {
this.mainactivity= mainactivity;
}
@Provides // 关键字,标记具体提供依赖对象的方法
MainActivity providerMainActivity (){
return mainactivity;
}
*******************添加MainActivity ***********************
public class MainActivity extends AppCompatActivity{
@Inject
Person person3;
@Inject
Person person4;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 构造桥梁对象
ActivityComponent maincomponent= DaggerActivityComponent.builder()
.ActivityModule(new ActivityModule())
.build();
//注入
maincomponent.inject(this);
// 打印两个对象的地址
Log.i("dagger","person3 = "+ person3.toString()+"; person4 = "+ person4.toString());
}
}
此时person 和person2 是由splashcomponent提供同一个对象。
person3和person4是由maincomponent提供的同一对象,但是person
和person3,person4不是同一对象 ,这是因为maincomponent和splashcomponent不是同一个对象。
3.4@MapKey
这个注解用于定义依赖集合(映射和集)。
定义
@MapKey(unwrapValue = true)
@interface TestKey {
String value();
}
提供依赖
@Provides(type = Type.MAP)
@TestKey("foo")
String provideFooKey() {
return "foo value";
}
@Provides(type = Type.MAP)
@TestKey("bar")
String provideBarKey() {
return "bar value";
}
使用
@Inject
Map<String, String> map;
map.toString() // => „{foo=foo value, bar=bar value}”
3.5 Lazy
@Inject
Lazy lazyPerson; // 注入Lazy元素
@Inject
Provider providerPerson; // 注入Provider
// 调用该方法时才会去创建Person,以后每次调用获取的是同一个对象
Person person = lazyPerson.get();
Person person1 = lazyPerson.get();
person1,person指向同一对象 ;
// 调用该方法时才回去创建Person1,以后每次调用都会重新加载Module中的具体方法,根据Module中的实现,可能相同,可能不相同。
Person person2 = providerPerson.get();
Person person3 = providerPerson.get();
person2 和person3 可能相同,可能不相同。
3.6 Component依赖
Component之间的关系有: 依赖(dependencies),包含(SubComponent),继承方式(extends)
http://blog.csdn.net/soslinken/article/details/70231089
经验总结: