1:什么是Dagger2 ?
简单的说它是DI(动态注入)框架,在降低代码依赖耦合方面效果显著。现由Google在维护。
2:如何使用Dagger2 ?
配置:
在项目build.gradle(Project:xxx)中添加如下代码:
dependencies {
classpath 'com.android.tools.build:gradle:2.1.0'
//添加apt插件
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
在build.gradle(Module:app)中添加如下代码
apply plugin: 'com.android.application'
//应用apt插件
apply plugin: 'com.neenbedankt.android-apt'
...
dependencies { ...
compile 'com.google.dagger:dagger:2.4'
compile 'org.glassfish:javax.annotation:10.0-b28'
... }
在引入butterknife新版后之后,以上配置会提示警告,应改为以下:
项目build.gradle(Project:xxx)中移除:
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
build.gradle(Module:app)中移除:
apply plugin: 'com.neenbedankt.android-apt'
3:Dagger2 的使用样子
大体使用思路是这个样子的(基于MVP模式,不明白MVP的看谷歌官方去 : google mvp demo):
MVP接口:
public interface MyContract {
interface View{
void show(Object o);
}
interface Presenter{
void loadData(String pram);
}
}
public class MyPresenter implements MyContract.Presenter {
private MyContract.View view;
@Inject // <= 这里是使用Dagger2时的注解,后面会讲到
public MyPresenter(MyContract.View view){
this.view = view;
}
@Override
public void loadData(String pram) {
view.show("test");
}
}
测试activity:
public class TestActivity extends AppCompatActivity implements MyContract.View {
@BindView(R.id.btn)
Button btn;
@BindView(R.id.tvInfo)
TextView tvInfo;
@Inject
MyPresenter presenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
ButterKnife.bind(this);
DaggerMyComponent.builder().myModel(new MyModel(this)).build().inject(this);
}
@OnClick(R.id.btn)
public void onViewClicked() {
presenter.loadData("test");
}
@Override
public void show(Object o) {
tvInfo.setText("返回值");
}
}
Module类(生成依赖):
@Module //Dagger2 注解
public class MyModel {
MyContract.View view;
public MyModel(MyContract.View view){
this.view = view;
}
@Provides
public MyContract.View myView(){
return view;
}
@Provides
public OkHttpClient provideOkHttpClient() {
OkHttpClient okhttpClient = new OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.build();
return okhttpClient;
}
@Provides
public Retrofit provideRetrofit(OkHttpClient okhttpClient) {
Retrofit retrofit = new Retrofit.Builder()
.client(okhttpClient)
.baseUrl("https://api.github.com")
.build();
return retrofit;
}
}
Component类(提供依赖)
@Component(modules = MyModel.class)
public interface MyComponent {
void inject(TestActivity activity);
}
1:创建类用来提供依赖(使用@Module
注解,并将返回依赖的方法使用@Provides
注解)
2:创建Component接口,并用@Component(modules = MyModel.class)
标识该类,其中MyModel
就是上面@Module
注解的类。
3:在Activity中,用@Inject
标识要使用的依赖,同时依赖中的构造方法也用@Inject
标识(如果有构造方法的话,不然也可以在Module
中创建生成其他依赖的方法)
4:重建项目,会生成Dagger开头的Component类。
5:用生成Dagger开头的Component类初始化依赖,DaggerMyComponent.builder().myModel(new MyModel(this)).build().inject(this);
初始化依赖。
6:使用依赖。
- @Inject 带有此注解的属性或构造方法将参与到依赖注入中,Dagger2会实例化有此注解的类
- @Module 带有此注解的类,用来提供依赖,里面定义一些用@Provides注解的以provide开头的方法,这些方法就是所提供的依赖,Dagger2会在该类中寻找实例化某个类所需要的依赖。
- @Component 用来将@Inject和@Module联系起来的桥梁,从@Module中获取依赖并将依赖注入给@Inject
activity中用@Inject注解MyPresenter 说明MyPresenter 需要注入到activity中,使用@Inject时,不能用private修饰符修饰类的成员属性。进入MyPresenter 发现其构造函数也被@Inject注解,这样当Dagger2扫描到注解时会进入其构造函数,如果构造函数也被注解,那么会自动完成注入即初始化。
但依赖和他的构造函数是怎么建立其联系的呢?就是Component,Component是一个接口或者抽象类,用@Component注解标注,rebuild项目之后会自动生成Dagger开头的Component类(其实DaggerComponent就是实现了我们自己定义的Component)。
然后初始化依赖,如下:
DaggerMyComponent.builder().myModel(new MyModel(this)).build().inject(this);
通过new MyModel(this)将view传递到MyModel里,然后MyModel里的myView()方法返回这个View,当去实例化MyPresenter时,发现构造函数有个参数,此时会在MyModel里查找提供这个依赖的方法,将该View传递进去,这样就完成了presenter里View的注入。