本文转载自:https://github.com/EvilBT/-Dagger2Demo
Dagger2 是一款使用在Java和Android上的依赖注入的一个类库,用来解耦的。
简单使用@inject:
配置信息
使用Android Studio 创建一个新的项目,在Project的 build.gradle文件添加以下内容:
buildscript {
dependencies {
classpath 'me.tatarka:gradle-retrolambda:3.2.4'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
}
并在Module下的build.gradle添加以下内容:
apply plugin: 'com.neenbedankt.android-apt'
apply plugin: 'me.tatarka.retrolambda'
//将jdk版本设置成1.8版本
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
compile 'com.google.dagger:dagger:2.6'
apt 'com.google.dagger:dagger-compiler:2.6'
provided 'org.glassfish:javax.annotation:10.0-b28'
}
这样就基本完全了Dagger2的配置环境(顺便也配置了支持lambda表达式)。
创建一个javabean类,如下:
public class Poetry {
private String mPemo;
// 用Inject标记构造函数,表示用它来注入到目标对象中去
@Inject
public Poetry() {
mPemo = "你看那朵云,像不像你欠我的那200块钱";
}
public String getPemo() {
return mPemo;
}
}
此时这样子在MainActivity中的mPoetry对象是无法被注入的,因为MainActivity不知道去哪里找到它的实例去注入生成,这时我们需要一个连接器Component,让上面这两个类产生联系:
//用@Component表示这个接口是一个连接器,能用@Component注解的只能是interface或者抽象类
@Component
public interface MainComponent {
/**
* 需要用到这个连接器的对象,就是这个对象里面有需要注入的属性(被标记为@Inject的属性)
* 这里inject表示注入的意思,这个方法名可以随意更改,但建议就用inject即可。
*/
void inject(MainActivity activity);
}
运行一遍,AS中会根据我们写的连接类MainComponent来生成一些类
MainActivity中注入javabean类
如果不等AS生成上述源文件,使用DaggerMainComponent注入javabean就会报错:
public class MainActivity extends AppCompatActivity {
//添加@Inject注解,表示这个mPoetry是需要注入的
@Inject
Poetry mPoetry;
@InjectView(R.id.tv_poetry)
TextView tvPoetry;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.inject(this);
// 使用Dagger2生成的类 生成组件进行构造,并注入,注入完成后mPoetry才不为空
DaggerMainComponent.builder()
.build()
.inject(this);
tvPoetry.setText(mPoetry.getPemo());
}
}
运行结果如下:
上面MainActivity中的Poetry实例并不直接由MainActivity类创建,而是由MainActivityComponent类注入生成实例。以上就是一个简单的Dagger2示例。
@Module
依赖moudle对象
有时候我们并不能直接在构造函数里面添加@Inject注解,或者类中存在多个构造函数时,@Inject也只能注解其中一个构造函数,不能注解多个构造函数,这里是会产生歧义性,因为Dagger2无法确认调用哪一个构造函数来生成例的实例对象。另外一种情况是我们在项目中引用第三方类库时,也是无法直接在类构造函数中添加@Inject注解的,所以我们需要用到@Module注解了。 @Module是用来生产实例来注入对象的,它类似一个工厂,集中创建要注入的类的对象实例。下面我们引用一下Gson库来看看@Module是怎么使用的,创建MainModule类:
添加Gson依赖:
compile 'com.google.code.gson:gson:2.2.4'
@Module //@Module注解表示这个类提供生成一些实例用于注入
public class MainModule {
/**
* @return 返回注入对象
* @Provides 注解表示这个方法是用来创建某个实例对象的,这里我们创建返回Gson对象
* 方法名随便,一般用provideXXX结构
*/
@Provides
public Gson provideGson() {
return new Gson();
}
}
添加完这个类后,我们要与之前写的类产生关联,不然谁知道你这里提供了生成Gson实例的方法啊。修改MainCompontent
@Component(modules = MainModule.class)
public interface MainComponent {
/**
* 需要用到这个连接器的对象,就是这个对象里面有需要注入的属性被标记为@Inject的属性)
* 这里inject表示注入的意思,这个方法名可以随意更改,但建议就用inject即可。
*/
void inject(MainActivity activity);
}
在MainActivity里注入Gson实例
public class MainActivity extends AppCompatActivity {
//添加@Inject注解,表示这个mPoetry是需要注入的
@Inject
Poetry mPoetry;
@Inject
Gson mGson;
@InjectView(R.id.tv_poetry)
TextView tvPoetry;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.inject(this);
// 使用Dagger2生成的类 生成组件进行构造,并注入,注入完成后mPoetry才不为空
DaggerMainComponent.builder()
.build()
.inject(this);
// tvPoetry.setText(mPoetry.getPemo());
String json = mGson.toJson(mPoetry);
tvPoetry.setText(json);
}
}
运行结果:
Component可以依赖多个Module对象.
以上的构造方法与生成方法都是无参生成实例的,如果我们带参数应该怎么做了?我们创建多一个PoetryModule用于提供Poetry实例:
@Module
public class PoetryModule {
// 这个方法需要一个String参数,在Dagger2注入中,这些参数也是注入形式的,也就是
// 要有其他对方提供参数poems的生成,不然会造成编译出错
@Provides
public Poetry providePoetry(String poems){
return new Poetry(poems);//注意要同步在Poetry中生成有参构造
}
// 这里提供了一个生成String的方法,在这个Module里生成Poetry实例时,会查找到这里
// 可以为上面提供String类型的参数
@Provides
public String providePoems(){
return "只有意志坚强的人,才能到达彼岸";
}
}
修改MainComponent依赖:
@Component(modules = {MainModule.class, PoetryModule.class})
public interface MainComponent {
/**
* 需要用到这个连接器的对象,就是这个对象里面有需要注入的属性被标记为@Inject的属性)
* 这里inject表示注入的意思,这个方法名可以随意更改,但建议就用inject即可。
*/
void inject(MainActivity activity);
}
运行结果如下:
细心的同学就会发现了,我们提供了两个生成Poetry实例的方法,一个是在Poetry类的构造函数时候用@Inject提供的实例创建方法,一个是在PoetryModule中的@Privodes注解的providePoetry方法
而在上面的运行结果中我们发现是调用了PoetryModule提供的方法,这里就要说明一下优先级的问题,在上面这种既在构造函数中用@Inject提供注入来源,也在@Module中用@Privodes注解提供注入来源的,Dagger2是先从@Privodes查找类实例,如果找到了就用@Module提供的方法来创建类实例,如果没有就从构造函数里用@Inject注解的生成类实例,如果二者都没有,则报错。
简而言之,就是@Module的优先级高于@Inject。
另外这里还要说明一点,在providePoetry(String)方法中,String这个参数也是要注入提供的,必须也要有在同一个连接器里面有提供,其中在构建类实例的时候,会按照以下顺序执行:
1.从Module中查找类实例创建方法
2.Module中存在创建方法,则看此创建方法有没有参数
·如果有参数,这些参数也是由Component提供的,返回步骤1逐一生成参数类实例,最后再生成最终类实例
·如果无参数,则直接由这个方法生成最终类实例
3.Module中没有创建方法,则从构造函数里面找那个用@Inject注解的构造函数
·如果该构造函数有参数,则也是返回到步骤1逐一生成参数类实例,最后调用该构造函数生成类实例
·如果该构造函数无参数,则直接调用该构造函数生成类实例
以上就是一次注入生成类实例的生成步骤。
友情提示:其他注解方式详解和demo下载地址请参考本文转载出处:https://github.com/EvilBT/-Dagger2Demo