项目中一直都在用Dagger2框架,但是没有系统的研究Dagger2的使用及原理,今天就来写一些关于Dagger2的一些文章,来记录自己研究Dagger2的过程及心得。本篇文章先介绍基本使用
研究之前先看一个问题。看如下两端段代码:类A
package com.dagger2app;
import android.util.Log;
/**
* Created by xiaolong.wei on 2018/4/4.
*/
public class A {
public void show(){
Log.d("TAG", "show: this is A class");
}
}
类A中只有一个方法show();
类MainActivity如下:
package com.dagger2app;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
A a = new A();
a.show();
}
}
类MainActivity中在onCreate方法中定义并初始化A类型的变量a,并调用a.show()方法。这样MainActivity和A就有了依赖关系,MainActivity类依赖A。如果项目庞大,这种依赖关系会变多,导致类与类之间耦合度增高。将来APP更新发版,极有可能导致“牵一发动全身”的情况,例如:如果有很多依赖A类的类,现在需要修改A类的构造,在构造函数中传一个参数,这样会导致,所有依赖A类的类都需要做响应的修改,导致风险变高,为了解决这种问题,Dagger2横空出世。
在Android项目的build.gradle中引入
dependencies {
compile 'com.google.dagger:dagger:2.x'
annotationProcessor 'com.google.dagger:dagger-compiler:2.x'
}
接下来就可以愉快的使用Dagger2了,有以下两种方式可以提供依赖:
1、方式一:
修改上面的代码,在需要提供依赖的类中,给构造增加注解标识,表明它需要提供依赖,修改代码如下
package com.dagger2app;
import android.util.Log;
import javax.inject.Inject;
/**
* Created by xiaolong.wei on 2018/4/4.
*/
public class A {
@Inject
public A (){
}
public void show(){
Log.d("TAG", "show: this is A class");
}
}
然后新建Component标注的接口,此接口是依赖注入的管理类,也是连接依赖(A类)与目标类(MainActivity类)的桥梁;新建接口或抽象类,并用@Component标志注解,定义方法,方法名随意,不过建议方法名为inject,参数为需要被注入的类(MainActivity):
package com.dagger2app;
import dagger.Component;
/**
* Created by xiaolong.wei on 2018/4/4.
*/
@Component
public interface ModuleInjector {
void inject(MainActivity mainActivity);
}
新建完此接口后,需要build一下工程,Dagger2会帮我们自动生成此接口的实现类命名为DaggerXXX.class,其中XXX为你定义接口的名字,在这里就是DaggerModuleInjector。
接下来在MainActivity中修改a变量的声明方式,通过@Inject表明需要依赖的类,并获取DaggerModuleInjector实例,调用inject方法吧依赖注入进来,如下:
package com.dagger2app;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import javax.inject.Inject;
public class MainActivity extends AppCompatActivity {
@Inject
A a;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerModuleInjector.create().inject(this);//获取DaggerModuleInjector实例,调用inject方法
a.show();
}
}
以上就是Dagger2的第一种使用方式。
2、方式二
第三方库,不能修改源码,无法在构造方法中通过@Inject注解的方式提供依赖,这种情况下,就使用方式二。
假设类B为第三方库,不能修改源码:
package com.dagger2app;
import android.util.Log;
/**
* Created by xiaolong.wei on 2018/4/4.
*/
public class B {
public B(){
}
public void show(){
Log.d("TAG", "show: this is B class");
}
}
如果想通过Dagger2,把MainActivity对B类的依赖注入进去应该怎么做呢?
首先创建一个可以提供实例的类,类名如叫AppModule
package com.dagger2app;
import android.content.Context;
import dagger.Module;
import dagger.Provides;
/**
* Created by xiaolong.wei on 2018/4/4.
*/
@Module
public class AppModule {
@Provides
B provideB(){
return new B();
}
}
此类通过@Module注解,在类中定义方法,命名方式一般为proviceXXX的形式,当然也可以看心情随便写,但是此方法必须用注解@Provides去标注,并在方法中返回需要提供依赖的实例。
接下来需要把这个Module加入到Component中,即用@Component标注的接口中
package com.dagger2app;
import dagger.Component;
/**
* Created by xiaolong.wei on 2018/4/4.
*/
@Component(modules = AppModule.class)
public interface ModuleInjector {
void inject(MainActivity mainActivity);
}
在@Component后面通过(modules=AppModule.class)的形式(如果是多个Module,需要写为(modules={XXXModule.class,YYYModule.class}))加到Component中,
接下来在需要引用B类的类中。通过@Inject的方式去注解声明,形式同方式一中的类A
以上就是Dagger2的基本使用方式
出现四个注解
@Inject:可以注解在需要提供依赖的类的构造方法里,表明需要提供依赖;也可以注解在需要被注入的类的属性上,表明是注入进来的实例
@Component:通过此注解标注的接口,是连接提供依赖的类和需要依赖的类的桥梁
@Module:通过此标注的类,可以另一种方式提供依赖
@Provide:通过此标注注解的方法,需要返回提供依赖的实例
1、如果提供依赖的类,又依赖另外一个类,则另外一个类也需要通过@Inject或者@Module的方式提供依赖
2、两种方式的优先级是Module的方式大于@Inject的方式:如果@Module方式查找到了提供的依赖,则不再去查找@Inject方式是否有提供依赖了