欢迎转载,转载请标明出处: http://blog.csdn.net/johnny901114/article/details/58231038 本文出自:【余志强的博客】
分析的源码是基于Android Dagger2(一) 基本使用 的例子来分析对象是如何被注入的. 如果还没看上一篇文章, 可以先去看看.
在分析源码之前, 先理一理类与类之间的依赖关系 :
public class AddMenuBalanceFragment extends BaseFragment{ @Inject AddMenu BalancePResenter presenter;}从上面的代码可以看出 AddMenuBalanceFragment需要注入AddMenuBalancePresenter
Dagger2要想注入AddMenuBalancePresenter, 必须调用AddMenuBalancePresenter的构造方法:
而AddMenuBalancePresenter的构造方法又依赖View和MenuBalanceRepository, 这里的View就是Activity或者Fragment, 这个不能是我们new出来的,因为所有的界面都是由Android系统来创建和销毁的. 所以这个参数只能我们通过传递参数的方式传递给Dagger2.
要想提供MenuBalanceRepository Dagger2就必须要调用MenuBalanceRepository的构造方法 :
发现MenuBalanceRepository的构造方法又依赖IMenuBalanceSource.
它们的依赖关系可以用下图来表示:

通过面的图得知, 只要把IMenuBalanceSource构造出来了, MenuBalanceRepository也就可以构造出来了, 如果MenuBalanceRepository和View都有了就可以把AddMenuBalancePresenter构造出来了.
这样AddMenuBalanceFragment所需要的AddMenuBalancePresenter也就被注入了.
下面就分析下Dagger2生成的源码, 看看这些依赖到底是怎么被注入的.
我们分析源码的不能一下子扎进源码堆里不能自拔, 那么分析源码该如何下手, 我觉得应该从使用它的地方入手. 比如Dagger2, 使用它的地方也就是触发依赖注入的地方:
public class AddMenuBalanceFragment extends BaseFragment{ @Inject AddMenuBalancePresenter presenter; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); DaggerAddMenuBalanceComponent.builder() .menuBalanceRepoComponent(((Ccdapplication) getActivity().getApplication()).getMenuBalanceRepoComponent()) .addMenuBalancePresenterModule(new AddMenuBalancePresenterModule(this)) .build() .inject(this); //完成注入 }}从上面的代码可以直观的看出DaggerAddMenuBalanceComponent使用了Builder模式, 设置了两个参数 menuBalanceRepoComponent 和 addMenuBalancePresenterModule, 最后调用inject()把当前的Fragment作为参数传递进去了.
接下来看看inject()的实现 :
然后看看DaggerAddMenuBalanceComponent中 addMenuBalanceFragmentMembersInjector是怎么产生的:
从initialize方法里可以看出 addMenuBalanceFragmentMembersInjector依赖addMenuBalancePresenterProvider addMenuBalancePresenterProvider又依赖provideAddMenuBalanceViewProvider和getMenuBalanceRepositoryProvider
所以要想明白addMenuBalanceFragmentMembersInjector是怎么创建出来的, 就必须弄清楚addMenuBalancePresenterProvider,provideAddMenuBalanceViewProvider和getMenuBalanceRepositoryProvider.
从上面的代码可以看出, provideAddMenuBalanceViewProvider是通过AddMenuBalancePresenterModule_ProvideAddMenuBalanceViewFactory.create构建出来的:
然后看看构造方法和AddMenuBalancePresenterModule_ProvideAddMenuBalanceViewFactory.get()方法:
如此可见,AddMenuBalancePresenterModule_ProvideAddMenuBalanceViewFactory.get方法的返回值是通过传递进去的module.provideAddMenuBalanceView()提供的,这个module就是在Fragment中DaggerAddMenuBalanceComponent.build的时候设置进去的,代码如下:
说白了AddMenuBalancePresenterModule_ProvideAddMenuBalanceViewFactory的module就是AddMenuBalancePresenterModule(this). 这里的this就是View了
看看AddMenuBalancePresenterModule的代码:
@Modulepublic class AddMenuBalancePresenterModule { private final AddMenuBalanceContract.View mView; public AddMenuBalancePresenterModule(AddMenuBalanceContract.View view) { mView = view; } @Provides AddMenuBalanceContract.View provideAddMenuBalanceView(){ return mView; }}所以provideAddMenuBalanceViewProvider.get返回的值就是View也就是我们的Fragment了。
所以provideAddMenuBalanceViewProvider的作用就是返回View , 至此provideAddMenuBalanceViewProvider讲解完毕了。
从上面的代码可以看出, 它通过一个匿名内部类来实现的。先看看匿名内部类中的menuBalanceRepoComponent属性
这里的menuBalanceRepoComponent是build.menuBalanceRepoComponent,DaggerAddMenuBalanceComponent.build我们只在AddMenuBalanceFragment里设置了参数了,如下:
从代码可以看出menuBalanceRepoComponent就是((CcdApplication) getActivity().getApplication()).getMenuBalanceRepoComponent()
Ok, 那我们看看CcdApplication.getMenuBalanceRepoComponent() :
所以匿名内部类(Factory)中的getMenuBalanceRepositoryProvider属性就是DaggerMenuBalanceRepoComponent.
然后再看匿名内部类(Factory)的get()方法, 返回的是 DaggerMenuBalanceRepoComponent.getMenuBalanceRepository();, getMenuBalanceRepository()方法具体是怎么实现的:
发现该方法返回的是menuBalanceRepositoryProvider.get(); , 那么menuBalanceRepositoryProvider是什么东西?
menuBalanceRepositoryProvider是在DaggerMenuBalanceRepoComponent.initialize(builder)中初始化:
从这段代码可以看出 menuBalanceRepositoryProvider初始化依赖于provideRemoteDataSourceProvider
所以又得先分析下 provideRemoteDataSourceProvider了, provideRemoteDataSourceProvider的初始化需要builder.menuBalanceRepoModule, 这个builder.menuBalanceRepoModule是在我们调用build的时候Dagger2创建的:
所以builder.menuBalanceRepoModule = new MenuBalanceRepoModule() , MenuBalanceRepoModule类的代码如下:
provideRemoteDataSourceProvider属性需要MenuBalanceRepoModule_ProvideRemoteDataSourceFactory.create创建出来的, 那来看看这个工厂方法 :
create方法的参数module就是我们刚刚分析的MenuBalanceRepoModule, 工厂方法的get方法返回的就是:
所以provideRemoteDataSourceProvider的作用就是提供new MenuBalanceRemoteSource()对象的.
menuBalanceRepositoryProvider属性依赖的参数provideRemoteDataSourceProvider讲完了, 那么就可以分析menuBalanceRepositoryProvider属性了:
MenuBalanceRepository_Factory类:
@Override public MenuBalanceRepository get() { return new MenuBalanceRepository(remoteSourceProvider.get()); } public static Factory<MenuBalanceRepository> create( Provider<IMenuBalanceSource> remoteSourceProvider) { return new MenuBalanceRepository_Factory(remoteSourceProvider); }它的get()方法new了一个MenuBalanceRepository, 构造这个MenuBalanceRepository需要MenuBalanceRemoteSource参数,通过传进来的provideRemoteDataSourceProvider提供即可.
所以menuBalanceRepositoryProvider的作用就是提供new MenuBalanceRepository对象的.
所以DaggerMenuBalanceRepoComponent.getMenuBalanceRepository()方法返回的就是MenuBalanceRepository
再来回顾下匿名内部类(Factory) :
this.getMenuBalanceRepositoryProvider = new Factory<MenuBalanceRepository>() { private final MenuBalanceRepoComponent menuBalanceRepoComponent = builder.menuBalanceRepoComponent; @Override public MenuBalanceRepository get() { return Preconditions.checkNotNull( menuBalanceRepoComponent.getMenuBalanceRepository(), "Cannot return null from a non-@Nullable component method"); } };到现在为止, 我们就可以解释匿名内部类get()方法返回的是什么了, 返回就是MenuBalanceRepository对象.
所以getMenuBalanceRepositoryProvider属性的作用就是提供MenuBalanceRepository对象的.
addMenuBalancePresenterProvider属性初始化所依赖的provideAddMenuBalanceViewProvider和getMenuBalanceRepositoryProvider都分析完毕了, 现在就可以分析addMenuBalancePresenterProvider属性了.
通过上面的分析我们知道:
provideAddMenuBalanceViewProvider属性的作用就是返回View
getMenuBalanceRepositoryProvider属性的作用就是提供MenuBalanceRepository对象的
看看addMenuBalancePresenterProvider初始化代码如下:
AddMenuBalancePresenter_Factory类:
通过它的get()方法就知道该工厂方法返回一个AddMenuBalancePresenter实例, 构造AddMenuBalancePresenter需要的两个参数通过上面讲解了两个属性provideAddMenuBalanceViewProvider和getMenuBalanceRepositoryProvider提供.
所以addMenuBalancePresenterProvider属性的最终的作用就是提供AddMenuBalancePresenter对象的.
到此为止, 我们就知道了Presenter是怎么被构建出来的了.
接下来分析DaggerAddMenuBalanceComponent最后一个需要分析的属性addMenuBalanceFragmentMembersInjector
AddMenuBalanceFragment_MembersInjector类代码:
核心就是injectMembers方法, 该方法完成了Fragment中对Presenter的注入, injectMembers方法所需要的参数 presenterProvider 就是addMenuBalancePresenterProvider属性(提供AddMenuBalancePresenter对象的).
因为DaggerAddMenuBalanceComponent.inject()方法调用了AddMenuBalanceFragment_MembersInjector.injectMembers.
所以为什么说调用DaggerAddMenuBalanceComponent.inject()方法就完成了依赖注入操作.
所以这也就是为什么需要在Fragment中调用它了, 如下代码所示:
public class AddMenuBalancePresenter implements AddMenuBalanceContract.Presenter { private final AddMenuBalanceContract.View mView; private final MenuBalanceRepository mMenuBalanceRepository; @Inject AddMenuBalancePresenter(AddMenuBalanceContract.View view, MenuBalanceRepository mMenuBalanceRepository) { this.mView = view; this.mMenuBalanceRepository = mMenuBalanceRepository; }}上面的源码分析流程可以用如下图来表示 :

Dagger2生成类我们写的Component和Module类对应关系
AddMenuBalanceComponent(Interface) –> DaggerAddMenuBalanceComponent implements AddMenuBalanceComponent
AddMenuBalancePresenterModule –> AddMenuBalancePresenterModule_ProvideAddMenuBalanceViewFactory
MenuBalanceRepoComponent(Interface) –> DaggerMenuBalanceRepoComponent implements MenuBalanceRepoComponent
MenuBalanceRepoModule –> MenuBalanceRepoModule_ProvideRemoteDataSourceFactory
从上面的源码分析,Dagger2生成的源码大量使用了Builder、Factory模式。
新闻热点
疑难解答