关于dagger2在这里
关于依赖注入的基础知识在这里
导入
根目录build.gradle文件:
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
项目build.gradle文件:
apply plugin: 'android-apt'
apt 'com.google.dagger:dagger-compiler:2.2'
compile 'com.google.dagger:dagger:2.2'
//java注解
provided 'org.glassfish:javax.annotation:10.0-b28'
\\
Dagger2的每一个概念:
@Inject: 通常在需要依赖的地方使用这个注解。换句话说,你用它告诉Dagger这个类或者字段需要依赖注入。这样,Dagger就会构造一个这个类的实例并满足他们的依赖。
@Module: Modules类里面的方法专门提供依赖,所以我们定义一个类,用@Module注解,这样Dagger在构造类的实例的时候,就知道从哪里去找到需要的 依赖。modules的一个重要特征是它们设计为分区并组合在一起(比如说,在我们的app中可以有多个组成在一起的modules)。
@Provide: 在modules中,我们定义的方法是用这个注解,以此来告诉Dagger我们想要构造对象并提供这些依赖。
@Component: Components从根本上来说就是一个注入器,也可以说是@Inject和@Module的桥梁,它的主要作用就是连接这两个部分。 Components可以提供所有定义了的类型的实例,比如:我们必须用@Component注解一个接口然后列出所有的
@Modules组成该组件,如 果缺失了任何一块都会在编译的时候报错。所有的组件都可以通过它的modules知道依赖的范围。
@Scope: Scopes可是非常的有用,Dagger2可以通过自定义注解限定注解作用域。后面会演示一个例子,这是一个非常强大的特点,因为就如前面说的一样,没 必要让每个对象都去了解如何管理他们的实例。在scope的例子中,我们用自定义的
@PerActivity注解一个类,所以这个对象存活时间就和 activity的一样。简单来说就是我们可以定义所有范围的粒度(@PerFragment, @PerUser, 等等)。
Qualifier: 当类的类型不足以鉴别一个依赖的时候,我们就可以使用这个注解标示。例如:在Android中,我们会需要不同类型的context,所以我们就可以定义 qualifier注解’@ForApplication’和“@ForActivity”,这样当注入一个context的时候,我们就可以告诉 Dagger我们想要哪种类型的context。
使用
看了基础介绍后,然后就是怎么用了
就用一个非常简单的例子来说明怎么使用,现在有两个类:
public class Motor {
private int rpm;
public Motor(){
this.rpm = 0;
}
public int getRpm(){
return rpm;
}
public void accelerate(int value){
rpm = rpm + value;
}
public void brake(){
rpm = 0;
}
}
public class Vehicle {
private Motor motor;
public Vehicle(Motor motor){
this.motor = motor;
}
public void increaseSpeed(int value){
motor.accelerate(value);
}
public void stop(){
motor.brake();
}
public int getSpeed(){
return motor.getRpm();
}
}
然后我们的需求是调用Vehicle里的increaseSpeed();设置速度然后调用getSpeed()显示;
一般通常的做法是:
Motor motor = new Motor();
Vehicle vehiclev = new Vehicle(motor);
vehicle.increaseSpeed(22);
Log.d(TAG,String.valueOf(vehicle.getSpeed()));
但是用dagger2的做法就不一样了, Vehicle 和 Motor 。 Motor 是独立类, Vehicle 是依赖类,所以首先先改变一下Vehicle类的构造函数,如下:
public class Vehicle {
private Motor motor;
@Inject
public Vehicle(Motor motor){
this.motor = motor;
}
public void increaseSpeed(int value){
motor.accelerate(value);
}
public void stop(){
motor.brake();
}
public int getSpeed(){
return motor.getRpm();
}
}
可以发现在构造函数上加了 @Inject;
然后我们需要创建一个VehicleModule:
@Module
public class VehicleModule {
@Provides
@Singleton
Motor provideMotor(){
return new Motor();
}
}
@Singleton 表示注解指明对象只能有一个实例
但这并没有结束,最后我们需要创建一个VehicleComponent来链接他们
@Singleton
@Component(modules = {VehicleModule.class})
public interface VehicleComponent {
void inject(MainActivity activity);
}
使用带 @Component 注解的接口连接依赖的提供者;这样就结束了,下面就是在MainActivity调用依赖了:
public class MainActivity extends AppCompatActivity {
private TextView text;
@Inject
Vehicle vehicle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView) findViewById(R.id.text);
DaggerVehicleComponent.builder()
.vehicleModule(new VehicleModule())
.build()
.inject(this);
vehicle.increaseSpeed(22);
text.setText(String.valueOf(vehicle.getSpeed()));
}
}
如上代码,先声明一个Vehicle对象并在对象上加上@Inject然后点击AndroidStudio的Build/Make Project;这样AS会自动帮你生成对应的代码去关联依赖(生成的代码位置在:app/build/generated/source/apt/debug);最后
DaggerVehicleComponent.builder()
.vehicleModule(new VehicleModule(new Motor()))
.build()
.inject(this);
初始化它后就可以使用了;看完后是不是很晕它为什么要这么写;为什么就可以成功了?别急后面为你解惑