说明:
Dagger2作用在于自动创建实例,省去了手动new实例的代码。另一作用在于实现在mvc、mvp等架构下,各层解耦。
有如下两种方式:
方式一:用 @Inject + @Inject + @Component 方式实现,new的那个实例可以更改源码且能被实例化时适用。
方式二:用 @Inject + (@Module + @Provides ) + @Component 方式实现,new的那个实例是三方jar包,不能改源码或不能被实例化时用这种方式。
一、加入依赖jar包:
在工程根/app目录下build.gradle中,加入依赖:
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
//dagger2依赖包
compile 'com.google.dagger:dagger:2.+'
annotationProcessor 'com.google.dagger:dagger-compiler:2.+'
}
二、用 @Inject + @Inject + @Component 方式实现(此方式只适用于非第三方jar,即可以在被创建类的构造方法前加上@Inject):
1.在需要new的类构造方法上加@Inject:
/**
* 网络请求API,供UserPresenter调用
*/
public class UserApi {
/**
* 加上@Inject,PresenterComponent类就可以创建实例
*/
@Inject
public UserApi() {
}
/**
* 此方法供UserPresenter调用
*/
public void getUserInfoByNet(String userId) {
}
}
2.在使用的类的成员变量(属性注入)或方法(方法注入)加上@Inject:
/**
* 业务类,供Activity调用
*/
public class UserPresenter {
/**
* 属性注入,此处@Inject与UserApi构造方法前的@Inject相对应
*/
@Inject
UserApi mUserApi;
// /**
// * 方法注入(在构造方法后执行),用方法注入时mUserApi前不能加@Inject,此处@Inject与UserApi构造方法前的@Inject相对应
// */
// @Inject
// public void setUserApi(UserApi userApi) {
// this.mUserApi = userApi;
// }
public UserPresenter() {
//DaggerPresenterComponent是自动生成的,基于PresenterComponent接口,newInstance是PresenterComponent接口中定义的方法名
DaggerPresenterComponent.create().newInstance(this);
}
/**
* 此方法供调用api中的getUserInfoByNet方法
*/
public void getUserInfoByPresenter(String userId) {
//mUserApi实例会自动创建
mUserApi.getUserInfoByNet(userId);
}
}
3、创建连接组件Component,用于连接定义与创建:
/**
* 此类用于创建UserApi实例(UserApi构造方法用@Inject标注),并注入给UserPresenter中定义的mUserApi变量(此变量用@Inject标注),UserApi是被创建者,UserPresenter是使用者(使用UserApi对象)
*/
@Component
public interface PresenterComponent {
/**
* 此方法名随意,外部调用方式:DaggerPresenterComponent.create().newInstance(this);
*/
void newInstance(UserPresenter presenter);
}
三、 用 @Inject + (@Module + @Provides ) + @Component 方式实现(创建三方jar包中的类创建时)
1.创建管理实例的类,类前加上@Module,每个创建三方类实例的方法加上@Provides:
/**
* 此类用于创建三方jar包中的实例
*/
@Module
public class JarModule {
/**
* 此方法创建三方类实例,需要以@Provides标注,方法名随意
*/
@Provides
Socket newSocket() {
return new Socket();
}
}
2.在使用的类的成员变量(属性注入)或方法(方法注入)加上@Inject:
/**
* 业务类,供Activity调用
*/
public class JarPresenter {
/**
* 属性注入,此处@Inject与JarModule标记了@Provides的方法相对应
*/
@Inject
Socket mSocket;
public JarPresenter() {
//DaggerJarComponent是自动生成的,基于JarComponent接口,newInstance是JarComponent接口中定义的方法名
DaggerJarComponent.create().newInstance(this);
}
/**
* 此方法供调用JarModule中的newSocket方法创建Socket实例
*/
public Socket getSocket() {
//mSocket实例会自动创建
return mSocket;
}
}
/**
* 此类用于调用JarModule类中标记了@Provides的方法,创建对应的实例,modules可以有多个,以"modules=a.class,modues=b.class分隔
*/
@Component(modules = JarModule.class)
public interface JarComponent {
/**
* 此方法名随意,外部调用方式:DaggerJarComponent.create().newInstance(this);
*/
void newInstance(JarPresenter presenter);
}
四、限定符@Named的使用(当创建实例的方法返回对象类型一样时,需要加@Named("标记名")进行区分):
1.创建管理实例的类,在创建对象的方法加@Named限定符,标记唯一性:
@Module
public class JarModule {
/**
* @Named("tag1"),tag1可以任意名称,用于创建实例时识别,与JarPresenter中的@Named("tag1")定义保持一样
*/
@Named("tag1")
@Provides
Socket newSocket() {
return null;
}
/**
* @Named("任意名称"),用于创建实例时识别
*/
@Named("tag2")
@Provides
Socket newServerSocket() {
//...
return null;
}
}
2.在使用的类的成员变量(属性注入)或方法(方法注入)加上@Named,用于找到对应的方法:
public class JarPresenter {
/**
* @Named("tag1"),此参数跟JarModule中的@Named("newSocket")对应
*/
@Inject
@Named("tag1")
public Socket mSocket;
//...
}
五、限定符@Qualifier的使用(作用跟@Named一致,区别于使用自定义注解):
1.定义自定义注解:
/**
* 自定义注解TAG1
*/
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface TAG1 {
}
/**
* 自定义注解TAG2
*/
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface TAG2 {
}
2.像@Named一样使用:
(1)在创建实例的方法前加上自定义注解:
@Module
public class JarModule {
/**
* @TAG1为自定义注解,用于创建实例时识别,与JarPresenter中的@TAG1定义保持一样
*/
@TAG1
@Provides
Socket newSocket() {
return null;
}
/**
* @TAG2为自定义注解,用于创建实例时识别,
*/
@TAG2
@Provides
Socket newServerSocket() {
return null;
}
}
public class JarPresenter {
/**
* @TAG1为自定义注解,此参数跟JarModule中的带有@TAG1注解的方法对应
*/
@Inject
@TAG1
public Socket mSocket;
//...
}
六、dependencies依赖的使用(属于@Component参数,定义Component基类,用于共享通用方法):
1.定义Module基类,将通用方法实现写在此类中:
/**
* Module基类,此类定义通用方法,与BaseComponent中的定义保持一致
*/
@Module
public class BaseModule {
/**
* 此方法和BaseComponent中的newString方法保持一致
*/
@Provides
String newString() {
return "新字符串";
}
}
2.定义Component基类,将Module基类中的通用方法进行定义
/**
* Component基类,此类定义通用方法,共享BaseModule中的newString方法
*/
@Component(modules = BaseModule.class)
public interface BaseComponent {
/**
* 此方法和BaseModule中的newString方法保持一致,不用加@Provides等注解
*/
String newString();
}
/**
* 此类依赖BaseComponent基类,共用了newString方法,又能使用JarModule中的方法
*/
@Component(dependencies = BaseComponent.class, modules = JarModule.class)
public interface JarComponent {
/**
* 此方法名随意,外部调用方式:DaggerJarComponent.create().newInstance(this);
*/
void newInstance(JarPresenter presenter);
}
4.使用Module基类中的通用方法创建实例:
/**
* 业务类,供Activity调用
*/
public class JarPresenter {
/**
* 会调用BaseModule中的newString方法创建String实例
*/
@Inject
public String mStr;
public JarPresenter() {
//DaggerJarComponent和DaggerBaseComponent是自动生成的,基于JarComponent和BaseComponent接口,newInstance是JarComponent接口中定义的方法名
DaggerJarComponent.builder().baseComponent(DaggerBaseComponent.create()).build().newInstance(this);
}
}
七、Subcomponent依赖的使用(作用等同dependencies):
1.定义Module基类,将通用方法实现写在此类中:
/**
* Module基类,此类定义通用方法,与BaseComponent中的定义保持一致
*/
@Module
public class BaseModule {
/**
* 此方法和BaseComponent中的newString方法保持一致
*/
@Provides
String newString() {
return "新字符串";
}
}
2.定义Component基类,将Module基类中的通用方法进行定义,并定义用于包含子Component类的方法:
/**
* Component基类,此类定义通用方法,共享BaseModule中的newString方法
*/
@Component(modules = BaseModule.class)
public interface BaseComponent {
/**
* 此方法为BaseModule中的newString方法的定义
*/
String newString();
/**
* 包含JarComponent类,JarComponent类必须为@Subcomponent注解,JarModule为JarComponent所关联的Module
*/
JarComponent getJarComponent(JarModule module);
}
/**
* @Subcomponent表明此类被BaseComponent基类包含,共用了newString方法,又能使用JarModule中的方法
*/
@Subcomponent(modules = JarModule.class)
public interface JarComponent {
/**
* 此方法名随意,外部调用创建实例:DaggerBaseComponent.create().getJarComponent(new JarModule()).newInstance(this);
*/
void newInstance(JarPresenter presenter);
}
4.使用Module基类中的通用方法创建实例:
/**
* 业务类,供Activity调用
*/
public class JarPresenter {
/**
* 会调用BaseModule中的newString方法创建String实例
*/
@Inject
public String mStr;
public JarPresenter() {
//DaggerBaseComponent包含JarComponent,可调用JarComponent接口中定义的newInstance方法创建实例
DaggerBaseComponent.create().getJarComponent(new JarModule()).newInstance(this);
}
}
八、创建实例的作用域@Scope(在同一个对象如Activity内部创建多次,都只生成一个对象):
1.定义自定义的作用域注解:
/**
* 自定义作用域注解ObjectScope,Module的方法和Component类前加上@ObjectScope,Module的方法创建出的实例为单例(前提:用@Inject标记的成员变量在同一个对象内,比如在同一个Activity内定义的)
*/
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ObjectScope {
}
/**
* 此类用于创建三方jar包中的实例
*/
@Module
public class JarModule {
/**
* @ObjectScope为自定义的作用域注解,跟JarComponent类的作用域注解保持一致
*/
@ObjectScope
@Provides
UserApi newUserApi() {
return new UserApi();
}
}
3.定义 Component类,在类前加上自定义注解:
/**
* @ObjectScope为自定义的作用域注解,跟JarModule类的newUserApi方法作用域注解保持一致
*/
@ObjectScope
@Component(modules = JarModule.class)
public interface JarComponent {
/**
* 此方法名随意,外部调用创建实例
*/
void newInstance(JarPresenter presenter);
}
/**
* 业务类,供Activity调用
*/
public class JarPresenter {
/**
* 加了作用域后,在JarPresenter对象内,成员变量mUserApi1和mUserApi2为同个对象,
*/
@Inject
public UserApi mUserApi1;
@Inject
public UserApi mUserApi2;
public JarPresenter() {
//DaggerJarComponent为自定义类
DaggerJarComponent.create().newInstance(this);
}
}
九、Lazy使用(懒加载,在使用此成员变量时,要调用.get方法,才会创建此变量的实例):
public class JarPresenter {
/**
* 用Lazy<类>括起来的变量,只有在调用.get()方法时才会创建实例
*/
@Inject
public Lazy<UserApi> mUserApi;
public JarPresenter() {
//...
}
public UserApi getUserApi(){
return mUserApi.get();
}
}