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

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

分析的源码是基于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的构造方法 :

@Singleton
public class MenuBalanceRepository implements IMenuBalanceSource {

    private final IMenuBalanceSource remoteSource;

    @Inject
    MenuBalanceRepository(@Remote IMenuBalanceSource remoteSource) {
        this.remoteSource = remoteSource;
    }
}

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

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

Android Dagger2(二)源码分析-对象是如何被注入的_第1张图片

通过面的图得知, 只要把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() {
          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 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的代码:

@Module
public 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() {
          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类的代码如下:

@Module
public 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 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 create(
      Provider 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() {
          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 viewProvider,
      Provider 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 create(
      Provider viewProvider,
      Provider 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 create(
      Provider 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 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); //完成注入
    }
}

上面的源码分析流程可以用如下图来表示 :

Android Dagger2(二)源码分析-对象是如何被注入的_第2张图片


Dagger2生成类我们写的Component和Module类对应关系

AddMenuBalanceComponent(Interface) --> DaggerAddMenuBalanceComponent implements AddMenuBalanceComponent

AddMenuBalancePresenterModule --> AddMenuBalancePresenterModule_ProvideAddMenuBalanceViewFactory

MenuBalanceRepoComponent(Interface) --> DaggerMenuBalanceRepoComponent implements MenuBalanceRepoComponent

MenuBalanceRepoModule --> MenuBalanceRepoModule_ProvideRemoteDataSourceFactory

从上面的源码分析,Dagger2生成的源码大量使用了BuilderFactory模式。


如果你觉得本文帮助到你,给我个关注和赞呗!

另外,我为 Android 程序员编写了一份:超详细的 Android 程序员所需要的技术栈思维导图

如果有需要可以移步我的 GitHub -> AndroidAll,里面包含了最全的目录和对应知识点链接,帮你扫除 Android 知识点盲区。 由于篇幅原因只展示了 Android 思维导图:
超详细的Android技术栈

你可能感兴趣的:(Android)