说在前面:别人都是从两个端出发开始连线,而我是从线开始寻找连接的端。
本文仅提供一个思考的方向,是我本人对Dagger2
的理解,如若错误请留言指正,3Q。并且本文打算私藏,由于同桌好友需要阅读,姑且公开了吧。
阅读本文前需要先阅读 littleKang
的文章 http://www.jianshu.com/p/39d1df6c877d
1: Component
首先确定我们的目的:为了解耦,我们使用依赖注入的方式,去分离变量的声明和实例化。若分离了实例化,则实例化需要打参数必定是通过某种方式去获得。而下面我要讲的就是这个参数(this)的传递过程。
Component
作为连接目标和源的桥梁,所以在Component
必定包含了目标和源的引用。所以看Google为我们生成的代码(大部分是工厂类),没错我们直接从这部分代码开始。
// Ours
@Component(modules = MainModule.class)
public interface MainComponent {
void inject(MainActivity activity);
}
// Google
public final class DaggerMainComponent implements MainComponent {
private Provider provideMainViewProvider;
private Provider mainPresenterProvider;
private MembersInjector mainActivityMembersInjector;
private DaggerMainComponent(Builder builder) {
assert builder != null;
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.provideMainViewProvider = MainModule_ProvideMainViewFactory.create(builder.mainModule);
this.mainPresenterProvider = MainPresenter_Factory.create(provideMainViewProvider);
this.mainActivityMembersInjector = MainActivity_MembersInjector.create(mainPresenterProvider);
}
@Override
public void inject(MainActivity activity) {
mainActivityMembersInjector.injectMembers(activity);
}
public static final class Builder {
private MainModule mainModule;
private Builder() {}
public MainComponent build() {
if (mainModule == null) {
throw new IllegalStateException(MainModule.class.getCanonicalName() + " must be set");
}
return new DaggerMainComponent(this);
}
public Builder mainModule(MainModule mainModule) {
this.mainModule = Preconditions.checkNotNull(mainModule);
return this;
}
}
}
根据
DaggerMainComponent.builder()
.mainModule(new MainModule(this))
.build()
.inject(this);
的调用顺序看Google生成的代码,
-
DaggerMainComponent
调用静态方法builder()
返回内部静态类Builder
的对象 - 接着调用的是
Builder
的方法mainModule()
去实例化属性mainModule
,而调用该方法时this
参数传递到了Module
- 接着调用
build()
方法,使用静态内部类完成DaggerMainComponent
的创建(直到这里可以发现Component
已经连接到了Module
),值得一说的就是在new DaggerMainComponent
时调用了initialize()
- 在
initialize()
中,初始化了三个属性(三个工厂类对象),这里需要注意到的是参数,MainModule_ProvideMainViewFactory
的参数是builder
,这本类中已经完成builder
的初始化;接着下面的两个属性的初始化都是以它上一个的对象作为参数,而且都是实例化完毕的!(直到这里知道,这里没有哪个是没有初始化的, That is good!) - 完成了
DaggerMainComponent
的创建就可以使用inject()
方法,该方法中调用了injectMembers()
方法,注入activity
参数,而改参数是MainActivity
给予的,这在理解上完全没问题的。(直到这里可以看到DaggerMainComponent
连接MainActivity
的苗头了,好像这里没看出连接了啥,嗯,确实是,后面会接着说这个问题)
2: Module
在1.
中已经知道了Module
的工厂类的create()
方法被调用,已经实现了初始化,那么我们下面直接从create()
方法开始看
// Ours
@Module
public class MainModule {
private final MainContract.View mView;
public MainModule(MainContract.View view) {
mView = view;
}
@Provides
MainContract.View provideMainView() {
return mView;
}
}
// Google
public final class MainModule_ProvideMainViewFactory implements Factory {
private final MainModule module;
public MainModule_ProvideMainViewFactory(MainModule module) {
assert module != null;
this.module = module;
}
@Override
public MainContract.View get() {
return Preconditions.checkNotNull(
module.provideMainView(), "Cannot return null from a non-@Nullable @Provides method");
}
public static Factory create(MainModule module) {
return new MainModule_ProvideMainViewFactory(module);
}
}
-
create()
方法调用了改工厂类的初始化方法,而参数module
是1.
中调用该工厂类的ceate()
方法时给予的,所以不要再考虑谁给的参数用来实例化 - 实例化好该工厂类之后,将
module.provideMainView()
返回,之后就可以供Factory
的对象获取对象mView
了
3: Presenter(或者是我们自己创建的类,供宿主(MainActivity)使用的类)
这里是一样的,在1.
中调用了create()
方法,直接从该方法开始分析
// Ours
public class MainPresenter {
MainContract.View mView;
@Inject
MainPresenter(MainContract.View view) {
mView = view;
}
}
// Google
public final class MainPresenter_Factory implements Factory {
private final Provider viewProvider;
public MainPresenter_Factory(Provider viewProvider) {
assert viewProvider != null;
this.viewProvider = viewProvider;
}
@Override
public MainPresenter get() {
return new MainPresenter(viewProvider.get());
}
public static Factory create(Provider viewProvider) {
return new MainPresenter_Factory(viewProvider);
}
}
-
create()
方法中实例化并返回该工厂类的对象,而该类中的get()
方法直接返回我们需要依赖的MainPresenter
对象,而实例化所需要的参数在create()
方法给出!(还没有思路的话就绕着这个参数返回阅读) - 直到这里,我们可以了解这么一个情况,从
MainActivity
中给予的参数经过一系列的传递,最后传到了MainPresenter()
中,那么也就是说,我们直接调用这里的get()
方法便可以直接获取MainPresenter
类的实例! - 那么好,经过一系列的传递后该对象得到了初始化有了,然而怎么讲这么实例传回
MainActivity
?
4: MembersInjector
在这里我们可以返回到1.
中的最后的问题:连接!
终于到这一步了,看到前面参数一层一层传递,初始化了各种的工厂类,等着你一个get()
的调用,我就给你初始化好的实例了!还是照样,代码搬上来说话。
public final class MainActivity_MembersInjector implements MembersInjector {
private final Provider mainPresenterProvider;
public MainActivity_MembersInjector(Provider mainPresenterProvider) {
assert mainPresenterProvider != null;
this.mainPresenterProvider = mainPresenterProvider;
}
public static MembersInjector create(
Provider mainPresenterProvider) {
return new MainActivity_MembersInjector(mainPresenterProvider);
}
@Override
public void injectMembers(MainActivity instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
instance.mainPresenter = mainPresenterProvider.get();
}
public static void injectMainPresenter(
MainActivity instance, Provider mainPresenterProvider) {
instance.mainPresenter = mainPresenterProvider.get();
}
}
在这里我还得提示一点就是1.
中的这个方法重写里面的调用
@Override
public void inject(MainActivity activity) {
mainActivityMembersInjector.injectMembers(activity);
}
- 在这里我们还是先看看已经在
1.
中初始化了的MainActivity_MembersInjector
对象的create()
方法干了啥:调用构造方法,并直接返回该工厂类的对象!(这会儿,看看1.
中调用injectMembers()
,或许你会激动点啥的...) - 对应的,我们直接找
injectMembers()
方法,该方法的实现就在这个工厂类里边儿,而且我们有点激动的发现,我们传进来的宿主MainActivity
的对象(引用)的属性mainPresenter
得到了赋值(初始化!),而等号右边的就是已经准备好了提供Present
实例的get()
方法! - 知道这里可以想到了,
Component
是连接两头的关键之处