dagger2 学习(一)
前言
记录一下自己的基本的认识,Dagger 2
的目的是为了解决依赖问题
当我们申明一个 User mUser
对象 ,此时mUser
并未实例化,而当我们需要实例化的时候,则需要调用new User()
而使用Dagger 2
的时候,我们只需要 @inject User mUser
然后在Activity
中调用DaggerXXXX....inject(this)
即可(假设是Activity,也可以是其他任何类),如下
@User mUser;
@ClassRoom mClassRoom;
...
DaggerXXXX....inject(this)// 只需要调用一次即可
...
mUser.get...
mClassRomm.get...
那为什么不直接new User()
呢,因为会面对一个依赖问题,而下面的例子并没有突出解决这个问题,所以暂且搁置不写,讨论到 @Module
时继续讨论( 面对 new User(params...)
时,需要其他依赖时, 配合 @Module
这个注解进行使用,会显得更干净)。
下面的记录就是最简单的注入,主要搞定了
new User()
这类无依赖的注入问题
Dagger 2 基本使用
1.@inject
使用, 一共两种使用地方
(1) 标记被注入的对象的构造方法
public class User {
int age;
@Inject// 标注构造方法
public User(){
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
(2) 标记注入目标处
public class MainActivity extends AppCompatActivity {
TextView mUserAgeTv;
@Inject User mUser;// 标注注入的对象
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mUserAgeTv = (TextView) findViewById(R.id.user_age_tv);
}
}
这样标注出了两个地方,一个被注入对象的构造方法,一个需要注入的对象,但是相互之间是没有关联的
写完这两个类,编译后,看一下生成的具体代码,验证一下
(3) @Inject public User()...
后生成的代码
public enum User_Factory implements Factory<User> {
INSTANCE;
@Override
public User get() {
return new User();// 真正生成 User 对象的地方
}
public static Factory<User> create() {
return INSTANCE;// 返还User_Factory 对象
}
}
(4) @Inject User mUser
生成的代码
public final class MainActivity_MembersInjector implements MembersInjector<MainActivity> {
private final Provider<User> mUserProvider;// 用来提供User对象的 Provider
public MainActivity_MembersInjector(Provider<User> mUserProvider) {
assert mUserProvider != null;
this.mUserProvider = mUserProvider;
}
public static MembersInjector<MainActivity> create(Provider<User> mUserProvider) {
return new MainActivity_MembersInjector(mUserProvider);
}
@Override
public void injectMembers(MainActivity instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
// 看起来像注入的地方 调用了 userProvider 然后调用了 get
instance.mUser = mUserProvider.get();
}
public static void injectMUser(MainActivity instance, Provider<User> mUserProvider) {
// 这个也是看起来像注入的地方 调用了 userProvider 然后调用了 get
instance.mUser = mUserProvider.get();
}
}
仔细看,发现两者生成的代码现在是无关的,接下来引入连接的注解
2.@Component
使用,连接上述的两个地方,进行注入
(1)使用
加入一个新的类,如下
@Component // 注解标记
public interface UserComponent {
void injectTo(MainActivity mainActivity);
// 注意此处方法的参数 MainActivity ,由此标记处要注入的类,而方法名其实可以是任何名字
// 被 @Component 标注的类,其具体编译后生成的代码,会有具体的实现类来处理,参考下文
}
看文档,只知道这是一个连接的,也不知道具体怎么连接的,只知道会生成一个DaggerUserComponent
类,生成代码在具体调用分析处,可具体参考
在MainActivity
加入 DaggerUserComponent.builder().build().injectTo(this)
就可以注入成功,如下:
MainActivity.java
public class MainActivity extends AppCompatActivity {
TextView mUserAgeTv;
@Inject User mUser;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mUserAgeTv = (TextView) findViewById(R.id.user_age_tv);// 加入这句
DaggerUserComponent.builder().build().injectTo(this);
mUserAgeTv.setText("" + mUser.getAge());
}
}
(2)那就结合调用整体,具体看下生成的代码吧
DaggerUserComponent.builder().build().injectTo(this);
调用主要分两条线,看注释
..builder().build()
1 -> 2 步骤 生成一个
DaggerUserComponent
对象,同时实例化出mainActivityMembersInjector
..injectTo(this);
3 步骤 是调用
MainActivity_MembersInjector
进行真正的注入
DaggerUserComponent.java
public final class DaggerUserComponent implements UserComponent {
private MembersInjector<MainActivity> mainActivityMembersInjector;
private DaggerUserComponent(Builder builder) {
assert builder != null;
initialize(builder);//2.1 初始化 builder 对象
}
public static Builder builder() {
return new Builder();// 1. 首先生成一个 Builder 对象
}
public static UserComponent create() {
return builder().build();
}
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
// 2.2 关键处,它调用的是之前生成 MainActivity_MembersInjector 的 create 方法
this.mainActivityMembersInjector = MainActivity_MembersInjector.create(User_Factory.create());
}
@Override
public void injectTo(MainActivity mainActivity) {//3. 最后调用 injectTo 方法
// 3.1 mainActivityMembersInjector 它由 2.2 转换出来
mainActivityMembersInjector.injectMembers(mainActivity);
}
public static final class Builder {
private Builder() {}
public UserComponent build() {
return new DaggerUserComponent(this);//2. 生成一个 DaggerUserComponent 对象
}
}
}
综上,整个连接过程就出来了
下图中 黄色部分,就是builder().build()
构建出MainActivity_MembersInjector
,中间调用了 User_Factory
来生成mUserProvider
下图紫色部分,就是injectTo()
进行注入,根据构建出的MainActivity_MembersInjector
,获取 User
构建的实例,进行赋值
最后
整个记录主要写了 Dagger 2 最基本的使用,处理了 new User()
此类操作。
当然这不是 Dagger 2
的精华部分,此处主要是为了看其生成的代码,及其基本的使用。
其生成的对应关系如下:
@User mUser
===> User_Factory.java
@User public User(){}
===> MainActivity_MembersInjector.java
(其中的 Provider<User> mUserProvider
)
@Component UserComponent{...}
===> DaggerUserComponent.java
其具体作用在上面的代码注释分析中已经写了,此处不重复
以上。
一家之言,如有错误,轻喷。