Dagger2进阶学习

在学习完Dagger2的基本用法后,为了进一步的了解Dagger2,还需要了解他的源码、dagger.android等知识。

1.Dagger2源码浅析

了解Dagger2的源码,就是了解Dagger2的注解处理器,因为他是处理注解的关键。我们从最关键的注解@Component着手,看下其注解器做了什么。

1.1 关于 BasicAnnotationProcessor

@Component 是Dagger中最重要的注解,我们需要看下它做了什么,所以就需要知道它的注解器做了什么。
先来看下它的部分代码:

// dagger/java/dagger/internal/codegen/ComponentProcessor.java
@AutoService(Processor.class) // 1
public class ComponentProcessor extends BasicAnnotationProcessor {  // 2
  ....
  @Override
  public SourceVersion getSupportedSourceVersion() {  // 3
    return SourceVersion.latestSupported();
  }

  @Override
  public Set<String> getSupportedOptions() {  // 4
    return Sets.union(
            ProcessingEnvironmentCompilerOptions.supportedOptions(),
            bindingGraphPlugins.allSupportedOptions())
        .immutableCopy();
  }

  @Override
  protected Iterable<? extends ProcessingStep> initSteps() {  // 5
     ....
  }
  ....
}

注释1: @AutoService的注解可以用来自动生成配置文件注册注解处理器。

注释2:ComponentProcessor继承自 BasicAnnotationProcessor,而不是和 EventBus、ButterKnife一样继承自AbstractProcessor

注释3:返回支持的JDK版本

注释4:返回支持的编译参数,这里指的是 Component…

注释5:初始化处理步骤。

BasicAnnotationProcessor是属于Google的Auto项目,来看看它的部分源码:

// auto/common/src/main/java/com/google/auto/common/BasicAnnotationProcessor.java 
public abstract class BasicAnnotationProcessor extends AbstractProcessor {
  ...
  @Override
  public final synchronized void init(ProcessingEnvironment processingEnv) {  // 1
    super.init(processingEnv);
    this.elements = processingEnv.getElementUtils();
    this.messager = processingEnv.getMessager();
    this.steps = ImmutableList.copyOf(initSteps());  // 2
  }

  // 3
  private ImmutableSet<? extends Class<? extends Annotation>> getSupportedAnnotationClasses() {
    checkState(steps != null);
    ImmutableSet.Builder<Class<? extends Annotation>> builder = ImmutableSet.builder();
    for (ProcessingStep step : steps) {  //4
      builder.addAll(step.annotations());
    }
    return builder.build();
  }

  @Override
  public final ImmutableSet<String> getSupportedAnnotationTypes() {  // 5
    ImmutableSet.Builder<String> builder = ImmutableSet.builder();
    for (Class<? extends Annotation> annotationClass : getSupportedAnnotationClasses()) {
      builder.add(annotationClass.getCanonicalName());
    }
    return builder.build();
  }

  @Override
  public final boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    ...
    process(validElements(roundEnv)); // 6
    postRound(roundEnv);  // 7
    ...
  }
}

注释1: init方法用来初始化处理器
注释2:调用了之前出现在 ComponentProcessorinitStep(),

注释3:返回处理器支持解析的注解集合(返回的是Set<Class>
注释4:遍历添加

注释5:返回支持的注解类型(返回的是 Set<String>

注释6:内部遍历所有的ProcessingStep,然后执行每个ProcessingStep的 process方法
注释7:解析完注解后的处理,子类可实现该方法完成Java文件的创建。

BasicAnnotationProcessor的作用是为了规范注解解析的过程,上述的代码其实并没有太多实质上的做的事情,就跟我们所定义的 BaseActivitiy、BaseFragment一样。

不过这里需要注意的是:
这个类定义了 ProcessingStep,它是BasicAnnotationProcessor体系里解析注解的最小逻辑单元,我们来看下它的代码:

// BasicAnnotationProcessor.java
  public interface ProcessingStep {
    // 处理注解的集合
    Set<? extends Class<? extends Annotation>> annotations();
    //处理注解对应的元素,返回没有进行处理的元素的集合
    Set<? extends Element> process(
        SetMultimap<Class<? extends Annotation>, Element> elementsByAnnotation);
  }

来看下之前注释6的process():

// BasicAnnotationProcessor.java
  private void process(ImmutableSetMultimap<Class<? extends Annotation>, Element> validElements) {
    for (ProcessingStep step : steps) {  // 1
      ImmutableSetMultimap<Class<? extends Annotation>, Element> stepElements =
          new ImmutableSetMultimap.Builder<Class<? extends Annotation>, Element>()
              .putAll(indexByAnnotation(elementsDeferredBySteps.get(step), step.annotations()))
              .putAll(filterKeys(validElements, Predicates.<Object>in(step.annotations())))
              .build(); // 2
      if (stepElements.isEmpty()) {
        elementsDeferredBySteps.removeAll(step);
      } else {
        Set<? extends Element> rejectedElements = step.process(stepElements);  // 3
        elementsDeferredBySteps.replaceValues(
            step, transform(rejectedElements, ElementName::forAnnotatedElement));
      }
    }
  }

注释1:遍历所有的 ProcessingStep

注释2:获取一个step需要处理的 Element的集合,主要通过 setp.annotation() 过滤掉不是该step需要处理的注解。
比如说一个注解,他需要处理的Element集合为{方法/ 属性 / 类…}

注释3:如果集合不为空,就调用step的 process,即子类实现的process方法。

BasicAnnotationprocessor所做的事情可以总结成:

  1. 定义最小逻辑处理单元 ProcessingStep
  2. 让子类实现 initSteps(),这个方法里面,让子类自己去分出几个ProcessingStep
  3. 遍历每个 ProcessingStep,调用他们的 process

分成每个逻辑单元分布实现,这样做的好处就是:对于一个processor要处理众多的注解时,显然写在一个process方法里面未免太过混杂, BasicAnnotationprocessor对每个注解的处理进行了管理,清晰且简单。

那我们来看看 ComponentProcessor是如何在 initStep()里面创建 ProcessingSteps的:

// ComponentProcessor.java
  protected Iterable<? extends ProcessingStep> initSteps() {
    ProcessorComponent.factory().create(processingEnv, testingPlugins).inject(this);

    statisticsCollector.processingStarted();
    bindingGraphPlugins.initializePlugins();
    return Iterables.transform(
        processingSteps, // 1
        step -> new DaggerStatisticsCollectingProcessingStep(step, statisticsCollector));
  }

注释1:传入了 processingSteps,它就是ComponentProcessor定义的ProcessingStep集合,但是发现它没在这个方法中创建。在查看它是怎么来的时候,发现它也是通过了注解的方法实现创建…(套娃了),这里不讲过程,直接看看它的创建:

// ComponentProcessor.java
  @Module
  interface ProcessingStepsModule {
    @Provides
    static ImmutableList<ProcessingStep> processingSteps(
        MapKeyProcessingStep mapKeyProcessingStep,
        InjectProcessingStep injectProcessingStep, 
        MonitoringModuleProcessingStep monitoringModuleProcessingStep,
        MultibindingAnnotationsProcessingStep multibindingAnnotationsProcessingStep,
        BindsInstanceProcessingStep bindsInstanceProcessingStep,
        ModuleProcessingStep moduleProcessingStep,
        ComponentProcessingStep componentProcessingStep,  
        ComponentHjarProcessingStep componentHjarProcessingStep,
        BindingMethodProcessingStep bindingMethodProcessingStep,
        CompilerOptions compilerOptions) {
      return ImmutableList.of(
          mapKeyProcessingStep,
          injectProcessingStep,  
          monitoringModuleProcessingStep,
          multibindingAnnotationsProcessingStep,
          bindsInstanceProcessingStep,
          moduleProcessingStep,
          compilerOptions.headerCompilation()
              ? componentHjarProcessingStep
              : componentProcessingStep,   
          bindingMethodProcessingStep);
    }
  }  

在 ImmutatbleList.of 中 创建了很多个 xxxPrcessingStep,他们都间接的继承了 ProcessingStep,代表着每一种注解,可以看出来ComponentProcessor要处理的注解有 @MapKey、@Inject、@Mutibinding、@Module、@Component等等。

所以真正实现process方法,都是在这些 xxxProcessingStep.process()中,这里以 @Inject为例子,看看他是怎么实现对 @Inject注解的处理。

1.2 从InjectProcessingStep到Inject文件的生成

InjectProcessingStep实现了继承了 TypeCheckingProcessingStep

// InjectProcessingStep.java
final class InjectProcessingStep extends TypeCheckingProcessingStep<Element> {
  private final ElementVisitor<Void, Void> visitor;

  @Inject
  InjectProcessingStep(InjectBindingRegistry injectBindingRegistry) {
    super(e -> e);
    this.visitor =
        new ElementKindVisitor8<Void, Void>() {      // 构造一个访问者,对不同的Element做出反应
          @Override
          public Void visitExecutableAsConstructor(
              ExecutableElement constructorElement, Void aVoid) {
            injectBindingRegistry.tryRegisterConstructor(constructorElement);
            return null;
          }

          @Override
          public Void visitVariableAsField(VariableElement fieldElement, Void aVoid) {
            injectBindingRegistry.tryRegisterMembersInjectedType(
                MoreElements.asType(fieldElement.getEnclosingElement()));
            return null;
          }

          @Override
          public Void visitExecutableAsMethod(ExecutableElement methodElement, Void aVoid) {
            injectBindingRegistry.tryRegisterMembersInjectedType(
                MoreElements.asType(methodElement.getEnclosingElement()));
            return null;
          }
        };
  }

  @Override
  public Set<Class<? extends Annotation>> annotations() {
    return ImmutableSet.of(Inject.class);
  }

  @Override
  protected void process(
      Element injectElement, ImmutableSet<Class<? extends Annotation>> annotations) {
    injectElement.accept(visitor, null);
  }
}

可以看到 Inject注解器也实现了给自己注解。我们先不用搞懂它是怎么给自己实现注解处理的。
我们先看看 被@Inject修饰的构造方法里面做了什么:创建了一个 ElementKindVisitor8对象并赋值给了 ElementVisitor类型的 vistor。然后又在 process()中调用了 Element.accept(visitor)

这个环节的操作,使用了面向对象编程的设计模式中 “访问者模式”。当Android中提到访问者模式的例子时,Dagger2中这块地方,就是被拿出来讲解的最经典的例子= = 。所以要看懂这块代码的结构,先要搞清楚什么是访问者模式,对此,我还专门学习写了一篇出来,请参考:浅学设计模式之访问者模式(9/23)

从命名上就很显然的看出:

  • Element是元素类,它定义了 accept(ElementVistor)方法,来接收访问者
  • ElementVistor是访问者的接口类,它代表的是一种状态,当给出一个状态时,它的子类要根据Element的种类,来做出对应的处理。

而上文中,提到的 ElementKinVistor8就是ElementVistor的一个子类(它是ElementVistor基于JDK8的实现),它根据在 process(Element)的不同的Element做出不同的反应:

  • 当传入的Element是构造函数时,调用 visitExecutableAsConstructor(),内部调用 InjectBindingRegistry.tryRegisterConstructor()实现
  • 当传入的Element是成员变量时,调用visitVariableAsField(),内部调用 InjectBindingRegistry.tryRegisterMembersInjectedType()实现
  • 当传入的Element是方法时,调用 visitExecutableAsMethod(),内部调用 InjectBindingRegistry.tryRegisterMembersInjectedType()实现

这说明了什么:@Inject注解可以修饰:构造函数、成员变量、方法。对于不同的元素,用不同的处理。
这就体现了访问者模式。

在源码中我们可以看到具体的实现是由 InjectBindingRegistry类实现,它是一个抽象类,真正的实现是在 InjectBindingRegistryImpl中, 上面三个方法最终都会调用 tryRegisterMembersInjectedType(),我们来看看它的实现:

// dagger/java/dagger/internal/codegen/validation/InjectBindingRegistryImpl.java 
  private Optional<MembersInjectionBinding> tryRegisterMembersInjectedType(
      TypeElement typeElement,
      Optional<TypeMirror> resolvedType,
      boolean warnIfNotAlreadyGenerated) {
    DeclaredType type = MoreTypes.asDeclared(typeElement.asType());   // 1
    Key key = keyFactory.forInjectConstructorWithResolvedType(type);  // 2
    MembersInjectionBinding cachedBinding = membersInjectionBindings.getBinding(key); // 3
    if (cachedBinding != null) {
      return Optional.of(cachedBinding);
    }

    ValidationReport<TypeElement> report =
        injectValidator.validateMembersInjectionType(typeElement);  // 4
    report.printMessagesTo(messager);  // 5
    if (report.isClean()) {
      MembersInjectionBinding binding = bindingFactory.membersInjectionBinding(type, resolvedType); // 6
      registerBinding(binding, warnIfNotAlreadyGenerated);  // 7
      for (Optional<DeclaredType> supertype = types.nonObjectSuperclass(type);
          supertype.isPresent();
          supertype = types.nonObjectSuperclass(supertype.get())) {
        getOrFindMembersInjectionBinding(keyFactory.forMembersInjectedType(supertype.get()));
      }
      return Optional.of(binding);
    }
    return Optional.empty();
  }

  private void registerBinding(ProvisionBinding binding, boolean warnIfNotAlreadyGenerated) {
    provisionBindings.tryRegisterBinding(binding, warnIfNotAlreadyGenerated);  // 8
    if (binding.unresolved().isPresent()) {
      provisionBindings.tryToGenerateBinding(binding.unresolved().get(), warnIfNotAlreadyGenerated);
    }
  }

注释1:将TypeElement转换成 DeclaredType
注释2:通过注释1获取的type,通过Key工厂获得一个Key
注释3:通过Key去内存中看看之前有没有缓存过该注解内容,如果缓存过则取缓存的的内容
注释4、5:在 messager上打印TypeElement信息
注释6、7:通过工厂模式创建出 注解信息 MembersInjectonBinding,它是 ProvisionBinding抽象类的子类,它的作用是描述一个被注解修饰的信息。然后调用 registerBinding()

注释8:将 注释7的 ProvisionBinding注册到 provisionBindings中,它的类型是 BindingsCollection<ProvisionBinding>,即专门用来收集注解信息。

到这里,通过 InjectProcessingStep.process()方法,@Inject修饰的所有信息,全都被注册到了 provisionBindings中。
我们都知道注解处理器无非就做两件事情:①收集注解信息 ②将这些信息写成Java文件

怎么实现第二步呢?在 BasicAnnotationProcessor中,在调用完 process()遍历执行完每个ProcessingStep后,还会执行postRound(),它会让子类来实现。
在 @Inject中,其Java文件的产生是在 ComponentProcessor中:

// ComponentProcessor.java
  protected void postRound(RoundEnvironment roundEnv) {
    statisticsCollector.roundFinished();
    if (roundEnv.processingOver()) {
      statisticsCollector.processingStopped();
    } else {
      try {
        injectBindingRegistry.generateSourcesForRequiredBindings(
            factoryGenerator, membersInjectorGenerator);   // 1
      } catch (SourceFileGenerationException e) {
        e.printMessageTo(processingEnv.getMessager());
      }
    }
    clearableCaches.forEach(ClearableCache::clearCache);
  }
}

注释1:调用 injectBindingRegistry.generateSourcesForRequiredBindings实际上就是调用:InjectBindingRegistryImpl.generateSourcesForRequiredBindings()

// dagger/java/dagger/internal/codegen/validation/InjectBindingRegistryImpl.java 
  @Override
  public void generateSourcesForRequiredBindings(
      SourceFileGenerator<ProvisionBinding> factoryGenerator,
      SourceFileGenerator<MembersInjectionBinding> membersInjectorGenerator)
      throws SourceFileGenerationException {
    provisionBindings.generateBindings(factoryGenerator);  // 1
    membersInjectionBindings.generateBindings(membersInjectorGenerator); // 2
  }

注释1:生成 XXX_Factory 类的Java文件
注释2:生成 XXXX_MemberInjector 类的Java
由于其细节都是文件生成,到这里就不再讲解下去了。

1.3 源码总结

虽然上面我讲解了只有关于 @Inject的注解处理,但是我相信触类旁通,Dagger2对其他的注解肯定也是做了类似的处理。
这里来总结一下 1.1、1.2节中所讲的知识。

(1)关于Dagger2 注解处理架构:
由于Dagger所要处理的注解很多, Inject、Module、Scope、Qualifier、Name、Component…为每个注解写一个Processor未免太枯燥,且难于管理,并且他们之间又存在着一些共性。
所以Dagger把这些共性抽了出来,并编写了 BasicAnnotationProcessor继承自AbstractProcessor。
并且实现了内部类ProcessingStep对应着每一个注解,它负责收集自己那部分注解修饰的信息。比如处理 @InjectInjectProcessingStep等。
BasicAnnotationPrcocessor.process() 会去遍历所有的 ProcessingStep.process()收集信息。
BasicAnnotationPrcocessor.postRound() 还会去根据需要产生Java文件(当然有些注解产生文件的入口不在这里)

(2)关于 XXXProcessingStep
间接的继承了 ProcessingStep,具备收集、注册信息的功能。
例如在 InjectProcessingStep中,它会把收集到的 Element,通过访问者模式,将Element信息注册到集合BindingsCollection中。
最后写文件的时候,就是根据这个集合的内容编写的。

2. dagger.android

Dagger针对Android平台提供了专门的库来简化注入过程。需要我们添加额外的依赖库。

在Android中Dagger的注入是分层级的,有对应用层级全局属性或服务(OkHttp、Retrofit、Database)的注入,有对Activity中的变量注入,也有对Fragment中的变量注入,对应Component的层级如下图所示:
在这里插入图片描述
下面举几个例子,看下使用 dagger.android 在上面层级中的使用。

2.1 MainActivity中一般对象的注入

(1)创建 MainActivitySubComponent:

@Subcomponent
public interface MainActivitySubComponent extends AndroidInjector<MainActivity>  {
    
    @Subcomponent.Builder
    abstract class Builder extends AndroidInjector.Builder<MainActivity>{}
}

MainActivitySubComponent 是MainActivity对应的Component,它是应用层级Component的子Component,所以使用 @Subcomponent注解。

MainActivitySubComponent 继承自 AndroidInjectorAndroidInjector是Android中的核心类(Activity、Fragment等)的注入器,可以完成对Activity或Fragment的成员变量的注入。

另外,我们还需要创建一个继承自AndroidInjector.Builder 的抽象类Builder,它的作用是创建 MainActivitySubComponent的实例。

(2)创建ActivityModule

@Module(subcomponents = MainActivitySubComponent.class)
public abstract class ActivityModule {
    
    //返回MainActivity对应的注入器工厂
    @Binds
    @IntoMap
    @ActivityKey(MainActivity.class)
    abstract AndroidInjector.Factory<? extends Activity> bindMainActivityInjectorFactory(MainActivitySubComponent.Builder builder);
    
    //返回其他Activity对应的注入器工厂
    ...
}

ActivityModule 可以提供各个Activity对应的AndroidInjector.Factory,也就是注入器工厂类。
subcomponents指定为MainActivitySubComponent,表示MainActivitySubComponent是任何使用ActivityModule的Component的子Component。

(3)创建应用层级的 AppComponent

@Component(modules = {AndroidInjectionModule.class, ActivityModule.class})
public interface AppComponent {
    void inject(App instance);
}

应用层级的 AppComponent安装了两个Module,一个是 AndroidInjectionModule(由dagger-android提供),一个是ActivityModule。
另外还提供注入到Application类中的注入方法inject,值得注意的是,inject方法中的参数为我们自定义的App类型,而非Application类。

(4)注入到 Application类

public class App extends Application implements HasActivityInjector {

    @Inject
    DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;

    @Override
    public void onCreate() {
        super.onCreate();
        DaggerAppComponent.create().inject(this);
    }

    @Override
    public AndroidInjector<Activity> activityInjector() {
        return dispatchingAndroidInjector;
    }
}

在应用的Application类中,我们需要实现接口HasActivityInjector返回一个全局的Activity的注入器 dispatchingActivityInjector,而它的初始化由 AppComponent来完成,即由AppComponent对应生成的 DaggerAppComponent在Application类的onCreate方法中注入。
(5)注入到MainActivity

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        AndroidInjection.inject(this);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

在MainActivity的 onCreate()中,调用 super.onCreate()前使用 AndroidInjection对MainActivity进行注入。

这个注入过程又是怎么完成的呢?实际上:

  1. AndroidInjection注入时会获取Application类里面的dispatchActivityInject
  2. 通过dispatchActivityInject查找到对应MainActivity的 AndroidInjector.Factory(即MainActivitySubComponent类中的Builder,该Buidler实现了AndroidInjector.Factory接口 )
  3. 然后使用Builder创建MainActivity的注入器AndroidInjector(即MainActivitySubComponent)
  4. 最终使用MainActvitySubComponent实现对MainActivity的注入,完成对MainActivity中对象的赋值。

我们可以看下 AndroidInjection.inject()

// AndroidInjection.java
  public static void inject(Activity activity) {
    checkNotNull(activity, "activity");
    Application application = activity.getApplication();  // 获取Application对象
    if (!(application instanceof HasActivityInjector)) {  // 希望Application实现了HasActivityInjector接口
      throw new RuntimeException(
          String.format(
              "%s does not implement %s",
              application.getClass().getCanonicalName(),
              HasActivityInjector.class.getCanonicalName()));
    }

    AndroidInjector<Activity> activityInjector =
        ((HasActivityInjector) application).activityInjector();    // 获取Application中的 dispatchingAndroidInjector对象
    checkNotNull(activityInjector, "%s.activityInjector() returned null", application.getClass());

    activityInjector.inject(activity);   //调用这个对象的inject方法(就是调用了MainActivitySubComponent的inject)
  }

(6)@ContributesAndroidInjector
通过上述的步骤,就可以完成对Activity的注入,但是整体略显繁琐,当我们想要注入某个Activity中,就必须要创建该Activity的Component,而且这些代码都是模板代码,不需要动脑子,另外每次增加一个Component,就要在ActivityModule的Subcomponent集合中添加它。

事实上,Activity对应的Component的创建可以使用注解 @ContributesAndroidInjector自动生成。
我们只需要修改 ActivityModule就可以了:

@Module
public abstract class ActivityModule {

//    //返回MainActivity对应的注入器工厂
//    @Binds
//    @IntoMap
//    @ActivityKey(MainActivity.class)
//    abstract AndroidInjector.Factory<? extends Activity> bindMainActivityInjectorFactory(MainActivitySubComponent.Builder builder);

    @ContributesAndroidInjector
    abstract MainActivity contributesMainActivityInjector();
}

2.2 MainActivity中TextView对象的注入

由于TextView对象需要TextViewModule提供,在构建MainActivity对应的Component时需要创建一个TextViewModule的实例,所以在ActivityModule中不能使用 @ContributesAndroidInjector自动生成MainActivitySubComponent,还是需要手动创建。

在MainActivitySubComponent内部类Builder中实现 seedInstance(),并创建抽象方法textViewModule接收TextViewModule对象作为参数,在seedInstance()中,调用 textViewModule方法传入一个TextViewModule实例。
这时MainActivityStubCoponent就具有注入TextView的能力。

@Subcomponent(modules = TextViewModule.class)
public interface MainActivitySubComponent extends AndroidInjector<MainActivity>  {

    @Subcomponent.Builder
    abstract class Builder extends AndroidInjector.Builder<MainActivity>{
        abstract void textViewModule(TextViewModule textViewModule);

        @Override
        public void seedInstance(MainActivity instance) {
            textViewModule(new TextViewModule(instance));
        }
    }
}

2.3 Fragment的注入

Activiy对应的注入器一般作为Application对应注入器的 Subcomponent,而Fragment对应的注入器可以是其他Fragment、Activity或Application的对应Component的Subcomponent,这要看Fragment的Module是安装到哪个Component上。

现在我们在MainActivity内部的MainFragment中也注入一个Java对象,步骤如下:

(1)创建FragmentModule
在FragmentModule中使用注解 @ContributesAndroidInjector,这样就可以自动生成MainFragment对应的Component。

@Module
public abstract class FragmentModule {
    
    @ContributesAndroidInjector
    abstract MainActivity.MainFragment contributeMainActivityInjector();
}

(2)安装FragmentModule
那么生成的Component是作为谁的Subcomponent呢?这就要看FragmentModule安装在哪里了。

这里,我们将FragmentModule安装到AppComponent中,那么MainFragment的Component将是AppComponent的Subcomponent,代码如下:

@Component(modules = {AndroidInjectionModule.class, ActivityModule.class
        , FragmentModule.class})
public interface AppComponent {
    void inject(App instance);
}

(3)注入Application
在Application类中实现 HasFragmentInjector接口,返回一个 dispatchingFragmentInjector,它同样会被AppComponent注入,完成初始化,后续会使用它来完成Fragment的注入:

public class App extends Application implements HasActivityInjector, HasFragmentInjector {

    @Inject
    DispatchingAndroidInjector<Fragment> dispatchingAndroidInjector;

    @Override
    public void onCreate() {
        super.onCreate();
        DaggerAppComponent.create().inject(this);
    }

    @Override
    public AndroidInjector<android.app.Fragment> fragmentInjector() {
        return dispatchingAndroidInjector;
    }
}

(4)注入Fragment

// MainFragment.java
...
  @Inject
  User mUser;

  @Override
  public void onAttach(Context context) {
      AndroidInjection.inject(this);
      super.onAttach(context);
  }

通过对Activity和Fragment的注入,我们知道使用Dagger-Android对Activity和Fragment的注入操作,最后都变成了一行代码:

AndroidInjection.inject(this);

不过上述的整体过程还是有一些繁琐,dagger-android还基于上面的代码封装了一层,形成了一套Android组件,让我们可以更方便上手使用。这里就不多赘述了,下次再学习怎么使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值