dagger2的配置及基本使用

时间:2021-12-13 21:02:34

一、配置:

1.1 在Project的gradle脚本中配置

  dependencies {
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}

1.2在Module的gradle脚本中配置

apply plugin: 'com.neenbedankt.android-apt'

dependencies {
apt 'com.google.dagger:dagger-compiler:2.11'
compile 'com.google.dagger:dagger:2.11'
}

二、代码实现

2.1、使用@Inject和@Component实现依赖注入

2.1.1: 在实体类的构造方法中标注@Injecct,表示其提供依赖,代码如下:

package testdagger.com.xn.testdagger2.modle;

import android.util.Log;
import javax.inject.Inject;

/**
* Created by 贺谋昌 on 2017/8/1.
*/


public class Watch {
@Inject
public Watch() {
}

public void work() {
Log.e("Watch", "Dagger2 watch is work");
}
}

2.1.2:创建注入器,即提供依赖和目标类之前的桥梁,是一个用@Conponent标注的接口

代码如下:

package testdagger.com.xn.testdagger2.component;
import dagger.Component;
import testdagger.com.xn.testdagger2.MainActivity;

/**
* Created by 贺谋昌 on 2017/8/1.
*/

@Component
public interface MainActivityComponent {
void inject(MainActivity activity);
}

其创建的方法中传入的参数为目标类的实体

2.1.3

在目标类中进行注入,并标注依赖注入的实体类

public class MainActivity extends Activity {

@BindView(R.id.btn)
Button btn;
@Inject
Watch watch;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
DaggerMainActivityComponent.create().inject(this);
}

@OnClick(R.id.btn)
public void onViewClicked() {
watch.work();
}
}

DaggerMainActivityComponent这个类是在component类完成之后进行reBuild后自动生成的类。

2.2、使用@Module和@Provides提供依赖

如果代码中使用了第三方的类库,那么目标类所需的依赖是无法进行标注的,因为无法更改实体类的源代码,比如一个jar包,这时我们用@Module和@Provides提供依赖。

2.2.1、新建一个标注@Module的类,并通过标注@Provides的方法返回实体类的对象,代码如下:

/**
* Created by 贺谋昌 on 2017/8/1.
*/

@Module
public class GsonModule {
@Provides
public Gson getGson() {
return new Gson();
}
}

2.2.2、使用已经创建的component来管理Module,只要在类名处标注上管理的是哪个Module即可,代码如下:

**
* Created by 贺谋昌 on 2017/8/1.
*/
@Component(modules = GsonModule.class)
public interface MainActivityComponent {
void inject(MainActivity activity);
}

2.2.3、在目标类中注入,并标注要使用的实体类,代码如下:

public class MainActivity extends Activity {

@BindView(R.id.btn)
Button btn;
@Inject
Watch watch;
@Inject
Gson gson;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
DaggerMainActivityComponent.create().inject(this);
}

@OnClick(R.id.btn)
public void onViewClicked() {
watch.work();
JSONObject object = new JSONObject();
try {
object.put("name", "贺贺");
object.put("age", 24);
Man man = gson.fromJson(object.toString(), Man.class);
Log.e("MainActivity", man.getName());
} catch (JSONException e) {
e.printStackTrace();
}

}
}

2.3、如果要注入的对象是抽象的则不能用@Inject来提供依赖,这时要用@Module,案例如下:

Engine是一个抽象类

public abstract class Engine {
public abstract String work();
}

MyEngine是Engine的子类

public class MyEngine extends Engine {
@Override
public String work() {
return "MyEngine is working";
}
}

Car持有Engine的对象

public class Car {
Engine engine;

@Inject
public Car(Engine engine) {
this.engine = engine;
}

public String run() {
return engine.work();
}
}

2.3.1、在component中提供一个方法,给Engine提供实例

@Module
public class GsonModule {

@Provides
public Engine getEngine() {
return new MyEngine();
}
}

2.3.2在MainActivity中注入

“`
@Inject
Car car;

DaggerMainActivityComponent.create().inject(this);
….
Log.e(“MainActivity”, car.run() );


### 2.4、@Name和Qualifier的基本使用
如果@Inject标注的多个构造或是@Provides标注的方法返回的是同一种类型的值,那么程序就不知道使用哪一个来提供依赖,这时就会报错,我们就可以使用@Qualifier来标注我们要使用的是哪一个,@Name是@Qualifier的一种实现。案例如下:
如果Engine的子类有两个,除了MyEngine之外还有HerEngine,在Module中返回的Engine的实例的方法中,有两个方法,一个返回MyEngine一个返回HerEngine,这时我们就要标注好哪个方法返回哪个实例,并且目标类需要哪个实例,可以用@name(字符串)也可以自定义Qualifier,示例代码如下:

//首先定义两个自定义的Qualifier
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface My {
}
….
….
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface Her {
}
….
//在Module中标注好,哪个方法对应的哪个类的实例
@Provides
@My
public Engine getEngine() {
return new MyEngine();
}

@Provides
@Her
public Engine getHerEngine() {
return new HerEngine();
}

// 标注好目标类需要哪个实例
public class Car {
Engine engine;

@Inject
public Car(@Her Engine engine) {
this.engine = engine;
}

public String run() {
return engine.work();
}

}


使用@Name来标注则更为简单

@Provides
@Named(“My”)
public Engine getEngine() {
return new MyEngine();
}

@Provides
@Named("Her")
public Engine getHerEngine() {
return new HerEngine();
}
//在需要依赖的类中同样使用@Name标注好
public class Car {
Engine engine;

@Inject
public Car(@Named("Her") Engine engine) {
this.engine = engine;
}

public String run() {
return engine.work();
}

}
“`