首页 > 系统 > Android > 正文

Android Dagger2(二)源码分析-对象是如何被注入的

2019-11-06 09:50:44
字体:
来源:转载
供稿:网友

欢迎转载,转载请标明出处: http://blog.csdn.net/johnny901114/article/details/58231038 本文出自:【余志强的博客】

分析的源码是基于Android Dagger2(一) 基本使用 的例子来分析对象是如何被注入的. 如果还没看上一篇文章, 可以先去看看.

在分析源码之前, 先理一理类与类之间的依赖关系 :

public class AddMenuBalanceFragment extends BaseFragment{ @Inject AddMenu BalancePResenter presenter;}

从上面的代码可以看出 AddMenuBalanceFragment需要注入AddMenuBalancePresenter

Dagger2要想注入AddMenuBalancePresenter, 必须调用AddMenuBalancePresenter的构造方法:

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; }}

AddMenuBalancePresenter的构造方法又依赖ViewMenuBalanceRepository, 这里的View就是Activity或者Fragment, 这个不能是我们new出来的,因为所有的界面都是由Android系统来创建和销毁的. 所以这个参数只能我们通过传递参数的方式传递给Dagger2.

要想提供MenuBalanceRepository Dagger2就必须要调用MenuBalanceRepository的构造方法 :

@Singletonpublic class MenuBalanceRepository implements IMenuBalanceSource { private final IMenuBalanceSource remoteSource; @Inject MenuBalanceRepository(@Remote IMenuBalanceSource remoteSource) { this.remoteSource = remoteSource; }}

发现MenuBalanceRepository的构造方法又依赖IMenuBalanceSource.

它们的依赖关系可以用下图来表示:

这里写图片描述

通过面的图得知, 只要把IMenuBalanceSource构造出来了, MenuBalanceRepository也就可以构造出来了, 如果MenuBalanceRepositoryView都有了就可以把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模式, 设置了两个参数 menuBalanceRepoComponentaddMenuBalancePresenterModule, 最后调用inject()把当前的Fragment作为参数传递进去了.

接下来看看inject()的实现 :

@Override public void inject(AddMenuBalanceFragment fragment) { addMenuBalanceFragmentMembersInjector.injectMembers(fragment); }

然后看看DaggerAddMenuBalanceComponentaddMenuBalanceFragmentMembersInjector是怎么产生的:

private void initialize(final Builder builder) { this.provideAddMenuBalanceViewProvider = AddMenuBalancePresenterModule_ProvideAddMenuBalanceViewFactory.create( builder.addMenuBalancePresenterModule); 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"); } }; this.addMenuBalancePresenterProvider = AddMenuBalancePresenter_Factory.create( provideAddMenuBalanceViewProvider, getMenuBalanceRepositoryProvider); this.addMenuBalanceFragmentMembersInjector = AddMenuBalanceFragment_MembersInjector.create(addMenuBalancePresenterProvider);}

initialize方法里可以看出 addMenuBalanceFragmentMembersInjector依赖addMenuBalancePresenterProvider addMenuBalancePresenterProvider又依赖provideAddMenuBalanceViewProvidergetMenuBalanceRepositoryProvider

所以要想明白addMenuBalanceFragmentMembersInjector是怎么创建出来的, 就必须弄清楚addMenuBalancePresenterProvider,provideAddMenuBalanceViewProvidergetMenuBalanceRepositoryProvider.


1) provideAddMenuBalanceViewProvider属性的分析

this.provideAddMenuBalanceViewProvider = AddMenuBalancePresenterModule_ProvideAddMenuBalanceViewFactory.create( builder.addMenuBalancePresenterModule);

从上面的代码可以看出, provideAddMenuBalanceViewProvider是通过AddMenuBalancePresenterModule_ProvideAddMenuBalanceViewFactory.create构建出来的:

public static Factory<AddMenuBalanceContract.View> create(AddMenuBalancePresenterModule module) { return new AddMenuBalancePresenterModule_ProvideAddMenuBalanceViewFactory(module); }

然后看看构造方法和AddMenuBalancePresenterModule_ProvideAddMenuBalanceViewFactory.get()方法:

public AddMenuBalancePresenterModule_ProvideAddMenuBalanceViewFactory( AddMenuBalancePresenterModule module) { assert module != null; this.module = module; } @Override public AddMenuBalanceContract.View get() { return Preconditions.checkNotNull( module.provideAddMenuBalanceView(), "Cannot return null from a non-@Nullable @Provides method"); }

如此可见,AddMenuBalancePresenterModule_ProvideAddMenuBalanceViewFactory.get方法的返回值是通过传递进去的module.provideAddMenuBalanceView()提供的,这个module就是在FragmentDaggerAddMenuBalanceComponent.build的时候设置进去的,代码如下:

public class AddMenuBalanceFragment extends BaseFragment{ //ignore other code DaggerAddMenuBalanceComponent.builder() .addMenuBalancePresenterModule(new AddMenuBalancePresenterModule(this)) .build() .inject(this); //完成注入 }}

说白了AddMenuBalancePresenterModule_ProvideAddMenuBalanceViewFactorymodule就是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讲解完毕了。


2) getMenuBalanceRepositoryProvider 属性的分析

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"); } };

从上面的代码可以看出, 它通过一个匿名内部类来实现的。先看看匿名内部类中的menuBalanceRepoComponent属性

这里的menuBalanceRepoComponent是build.menuBalanceRepoComponent,DaggerAddMenuBalanceComponent.build我们只在AddMenuBalanceFragment里设置了参数了,如下:

DaggerAddMenuBalanceComponent.builder() .menuBalanceRepoComponent(((CcdApplication) getActivity().getApplication()).getMenuBalanceRepoComponent()) .addMenuBalancePresenterModule(new AddMenuBalancePresenterModule(this)) .build() .inject(this);

从代码可以看出menuBalanceRepoComponent就是((CcdApplication) getActivity().getApplication()).getMenuBalanceRepoComponent()

Ok, 那我们看看CcdApplication.getMenuBalanceRepoComponent() :

public void onCreate() { //... mMenuBalanceRepoComponent = DaggerMenuBalanceRepoComponent.builder() .applicationModule(new ApplicationModule(getApplicationContext())) .build();}public MenuBalanceRepoComponent getMenuBalanceRepoComponent() { return mMenuBalanceRepoComponent;}

所以匿名内部类(Factory)中的getMenuBalanceRepositoryProvider属性就是DaggerMenuBalanceRepoComponent.

然后再看匿名内部类(Factory)的get()方法, 返回的是 DaggerMenuBalanceRepoComponent.getMenuBalanceRepository();, getMenuBalanceRepository()方法具体是怎么实现的:

public final class DaggerMenuBalanceRepoComponent implements MenuBalanceRepoComponent { @Override public MenuBalanceRepository getMenuBalanceRepository() { return menuBalanceRepositoryProvider.get(); }}

发现该方法返回的是menuBalanceRepositoryProvider.get(); , 那么menuBalanceRepositoryProvider是什么东西?

menuBalanceRepositoryProvider是在DaggerMenuBalanceRepoComponent.initialize(builder)中初始化:

private void initialize(final Builder builder) { this.provideRemoteDataSourceProvider = ScopedProvider.create( MenuBalanceRepoModule_ProvideRemoteDataSourceFactory.create( builder.menuBalanceRepoModule)); this.menuBalanceRepositoryProvider = ScopedProvider.create( MenuBalanceRepository_Factory.create(provideRemoteDataSourceProvider)); }

从这段代码可以看出 menuBalanceRepositoryProvider初始化依赖于provideRemoteDataSourceProvider

所以又得先分析下 provideRemoteDataSourceProvider了, provideRemoteDataSourceProvider的初始化需要builder.menuBalanceRepoModule, 这个builder.menuBalanceRepoModule是在我们调用build的时候Dagger2创建的:

public MenuBalanceRepoComponent build() { if (menuBalanceRepoModule == null) { this.menuBalanceRepoModule = new MenuBalanceRepoModule(); } return new DaggerMenuBalanceRepoComponent(this);}

所以builder.menuBalanceRepoModule = new MenuBalanceRepoModule() , MenuBalanceRepoModule类的代码如下:

@Modulepublic class MenuBalanceRepoModule { @Singleton @Provides @Remote IMenuBalanceSource provideRemoteDataSource() { return new MenuBalanceRemoteSource(); }}

provideRemoteDataSourceProvider属性需要MenuBalanceRepoModule_ProvideRemoteDataSourceFactory.create创建出来的, 那来看看这个工厂方法 :

@Override public IMenuBalanceSource get() { return Preconditions.checkNotNull( module.provideRemoteDataSource(), "Cannot return null from a non-@Nullable @Provides method"); } public static Factory<IMenuBalanceSource> create(MenuBalanceRepoModule module) { return new MenuBalanceRepoModule_ProvideRemoteDataSourceFactory(module); }

create方法的参数module就是我们刚刚分析的MenuBalanceRepoModule, 工厂方法的get方法返回的就是:

IMenuBalanceSource provideRemoteDataSource() { return new MenuBalanceRemoteSource(); }

所以provideRemoteDataSourceProvider的作用就是提供new MenuBalanceRemoteSource()对象的.

menuBalanceRepositoryProvider属性依赖的参数provideRemoteDataSourceProvider讲完了, 那么就可以分析menuBalanceRepositoryProvider属性了:

this.menuBalanceRepositoryProvider = ScopedProvider.create( MenuBalanceRepository_Factory.create(provideRemoteDataSourceProvider));

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

@Override public MenuBalanceRepository getMenuBalanceRepository() { return menuBalanceRepositoryProvider.get(); }

再来回顾下匿名内部类(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对象的.


3) addMenuBalancePresenterProvider 属性的分析

addMenuBalancePresenterProvider属性初始化所依赖的provideAddMenuBalanceViewProvidergetMenuBalanceRepositoryProvider都分析完毕了, 现在就可以分析addMenuBalancePresenterProvider属性了.

通过上面的分析我们知道:

provideAddMenuBalanceViewProvider属性的作用就是返回View

getMenuBalanceRepositoryProvider属性的作用就是提供MenuBalanceRepository对象的

看看addMenuBalancePresenterProvider初始化代码如下:

this.addMenuBalancePresenterProvider = AddMenuBalancePresenter_Factory.create( provideAddMenuBalanceViewProvider, getMenuBalanceRepositoryProvider);

AddMenuBalancePresenter_Factory类:

public AddMenuBalancePresenter_Factory( Provider<AddMenuBalanceContract.View> viewProvider, Provider<MenuBalanceRepository> mMenuBalanceRepositoryProvider) { assert viewProvider != null; this.viewProvider = viewProvider; assert mMenuBalanceRepositoryProvider != null; this.mMenuBalanceRepositoryProvider = mMenuBalanceRepositoryProvider; } @Override public AddMenuBalancePresenter get() { return new AddMenuBalancePresenter(viewProvider.get(), mMenuBalanceRepositoryProvider.get()); } public static Factory<AddMenuBalancePresenter> create( Provider<AddMenuBalanceContract.View> viewProvider, Provider<MenuBalanceRepository> mMenuBalanceRepositoryProvider) { return new AddMenuBalancePresenter_Factory(viewProvider, mMenuBalanceRepositoryProvider); }

通过它的get()方法就知道该工厂方法返回一个AddMenuBalancePresenter实例, 构造AddMenuBalancePresenter需要的两个参数通过上面讲解了两个属性provideAddMenuBalanceViewProvider和getMenuBalanceRepositoryProvider提供.

所以addMenuBalancePresenterProvider属性的最终的作用就是提供AddMenuBalancePresenter对象的.

到此为止, 我们就知道了Presenter是怎么被构建出来的了.


4) addMenuBalanceFragmentMembersInjector 属性的分析

接下来分析DaggerAddMenuBalanceComponent最后一个需要分析的属性addMenuBalanceFragmentMembersInjector

this.addMenuBalanceFragmentMembersInjector = AddMenuBalanceFragment_MembersInjector.create(addMenuBalancePresenterProvider);

AddMenuBalanceFragment_MembersInjector类代码:

public static MembersInjector<AddMenuBalanceFragment> create( Provider<AddMenuBalancePresenter> presenterProvider) { return new AddMenuBalanceFragment_MembersInjector(presenterProvider); } @Override public void injectMembers(AddMenuBalanceFragment instance) { if (instance == null) { throw new NullPointerException("Cannot inject members into a null reference"); } instance.presenter = presenterProvider.get(); }

核心就是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生成的源码大量使用了BuilderFactory模式。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表