3. Dagger2之Component

译文

标注一个接口或者抽象类从而根据modules集合生成一个完整的、依赖注入的实现。生成类会以@Component标注的类名加Dagger前缀命名。例如{@code @Component interface MyComponent {...}}会产生一个名为DaggerMyComponent的实现。

1. Component-methods(组件-方法)

每一个使用@Component标注的类型必须至少包含一个抽象的component方法。Component方法名字任意,但必须有符合provision或者merbers-injection格式的签名。

1.1 Provision methods(提供类方法)

Provision方法没有参数,并返回一个injectedprovided类型。每个方法可能还有一个限定注解。下面这些都是有效的provision方法声明:

   SomeType getSomeType();

   Set<SomeType> getSomeTypes();

   @PortNumber 
   int getPortNumber();

Provision方法,例如典型的injection位置,可以使用ProviderLazy更加显式地控制provision请求。一个Provider允许component的使用者通过Provider.get()provision执行任意次数的请求。Lazy只会请求一个单独的provision,但会延迟到第一次调用Lazy.get的时候。下面的provision方法请求的都是相同类型的provision,但是每个都暗含不同的语义:

    SomeType getSomeType();

    Provider<SomeType> getSomeTypeProvider();

    Lazy<SomeType> getLazySomeType();

1.2 Members-injection methods(成员注入型方法)

Members-injection方法有一个单独的参数,它将依赖注入到参数实例的每一个@Inject成员变量和方法中。成员注入型方法的返回值可能是void或者返回它的唯一参数以方便链式调用。下面是有效的成员注入型方法的声明:

   void injectSomeType(SomeType someType);

   SomeType injectAndReturnSomeType(SomeType someType);

一个无参的返回MembersInjector方法等价于一个成员注入方法。在返回的对象上调用MemberInjector.injectMembers与一个成员注入方法的效果是一样的,例如:

    MembersInjector<SomeType> getSomeTypeMembersInjector();

1.3 A note about covariance(不知道咋翻译,“协方差相关的一个知识点”?)

虽然一个类型的members-injection方法可以接收它的子类型实例,但是只有参数类型及其超类型的@Inject成员变量可以注入。其子类型的成员变量则不行。例如,给出下方的这些类型,当Child实例传入到member-injection方法injectSelf(Self instance)中时,只有ab可以注入到孩子的实例中。


   class Parent {
      @Inject A a;
   }

   class Self extends Parent {
      @Inject B b;
   }

   class Child extends Self {
      @Inject C c;
   }

2. Instantiation(实例化)

Component的实现例主要是通过生成的(generated) builder实例化的。builder的实例由componentbuilder()方法获得。如果component中内嵌了一个@Component.Builder类型,builder()方法会返回一个生成的该类型实现例。如果不存在内嵌的@Component.Builder, 返回的builder会设置每一个使用module和依赖类型的驼峰名命名的modulescomponent依赖。每个没有可见的默认构造方法的component依赖和module必须显式设置,但是任何带有默认或无参构造方法并对于component实例可访问的component依赖和module可以省略。下面这是一个component builder的使用示例:

   public static void main(String[] args) {
     OtherComponent otherComponent = ...;
     MyComponent component = DaggerMyComponent.builder()
         // required because component dependencies must be set
         .otherComponent(otherComponent)
         // required because FlagsModule has constructor parameters
         .flagsModule(new FlagsModule(args))
         // may be elided because a no-args constructor is visible
         .myApplicationModule(new MyApplicationModule())
         .build();
   }

在这个例子中,component没有component依赖且只有无参modules,生成的component也会有一个工厂方法create(). SomeComponent.create()SomeComponent.builder().build()都是有效和等价的。

3. Scope(作用域)

每个Dagger Component 使用scope注解标注可以关联一个scope. component的实现确保对于scoped binding,一个component实例当中只有一个provision. 如果component声明了一个scope, 在整个图的任何地方,它都只会包含unscoped bindings或者该scopebindings,例如

    @Singleton  @Component
   interface MyApplicationComponent {
     // this component can only inject types using unscoped or  @Singleton bindings
   }

为了获得与scope注解相关的合适行为,调用者负责在合适的时候创建Component实例。例如一个单例的component在应用中只能实例化一次,而一个RequestedScopedcomponent每次请求时都要实例化。因为component是自包含的实现,存在一个scope就像将所有引用丢给component实例一样简单。

4. Component relationships(组件的关系)

虽然使用单纯的unscoped bindings的单独的component有很多用处,许多应用还是有多scopes的多component交互的需求。Dagger提供(下面)两种机制关联Components.

4.1 Subcomponents(子组件)

关联两个components最简单的方式是声明一个Subcomponent. subcomponent行为完全就像一个component, 但是是在上一级(parent)componentsubcomponent内部生成它的实现。这样的关系允许subcomponent在被声明时 其实现继承它的parent的所有binding图。因为这个原因,一个subcomponent在它关联到parent之前是不完整的。

通过将subcomponent类列入parentcomponent的一个modulesubcomponents()属性中声明subcomponent.如此在parent component内部绑定了Subcomponent.Builder

subcomponents也可以通过parent componentsubcomponent上的工厂方法声明。这样的方法名字任意,但是必须返回该subcomponent.工厂方法的参数可以是该subcomponent任意数量的modules, 但至少必须包含缺少可见无参构造器的module.下面是一个工厂方法的示例,该方法从一个singleton-scopedparent创建一个request-scoped subcomponent:

    @Singleton  
    @Component
    interface ApplicationComponent {
     // component methods...
         RequestComponent newRequestComponent(RequestModule requestModule);
   }

4.2 Component dependencies(组件依赖)

虽然subcomponents是组成bindings子图最简单的方法,但是subcomponentsparent结合非常紧密;他们可以使用任意由他们的祖级(ancestor)componentsubcomponents定义的binding.作为可选项,通过声明component依赖,components只能使用来自其他的component接口的bindings。当一个类型用作component依赖,该依赖上面的每一个provision方法被绑定为一个provider.注意通过component依赖,只有暴露为provision方法的bindings是有效的。

猜你喜欢

转载自blog.csdn.net/kevinscsdn/article/details/79134550
今日推荐