(七) Dagger2 Component間的依賴

代碼示例

假如PlaygroundComponent注射器需要ZooComponent提供對象.

class Tiger {
    public void sleep() {
        System.out.println("Tiger sleeping");
    }
}
// 爲注射器提供工廠類
// @Module: 表示Dagger2可以將該類當作對象工廠.
@Module
class ZooModule {
    // @Provides: 表示Dagger2可以調用providerTiger()方法爲注射器提供對象.
    @Provides
    public Tiger providerTiger() {
        return new Tiger();
    }
}
// 注射器
// @Component: 該註解是用來創造對象提供方和對象使用間的橋樑,如何將對象賦值給成員變量都是由它來做的.
@Component(modules = {ZooModule.class})
interface ZooComponent {
    // 表示ZooComponent注射器可以向其他注射器提供ZooModule工廠類中的方法,也就是提供ZooModule工廠中創建的對象.
    Tiger providerTiger();
}

// 注射器
// dependencies: 表示PlaygroundComponent注射器依賴ZooComponent注射器,
// ZooComponent注射器向PlaygroundComponent注射器提供ZooModule工廠創建的Tiger對象.
@Component(dependencies = {ZooComponent.class})
interface PlaygroundComponent {
    Playground inject(Playground zoo);
}


// 對象使用者
public class Playground {
    // @Inject: 該註解用於成員變量上代表注射器可以爲該成員變量賦值對象.
    @Inject
    Tiger tiger;

    @Test
    public void 案例七() {
        // 創建ZooComponent注射器對象
        ZooComponent zooComponent = DaggerZooComponent.create();
        // DaggerPlaygroundComponent注射器依賴ZooComponent注射器,所以使用zooComponent()將ZooComponent注射器對象傳入DaggerPlaygroundComponent注射器中.
        // 創建好DaggerPlaygroundComponent對象之後調用inject()方法爲Playground對象中注入Tiger對象.
        DaggerPlaygroundComponent.builder().zooComponent(zooComponent).build().inject(this);
        tiger.sleep();
    }
}
Dagger2生成代碼閱讀

主要分析注射器之間產生依賴關係後,一個注射器如何才能使用其他注射器中的對象.

就着上面的案例來看下Degger2生成的代碼,生成的代碼在build\generated\sources\annotationProcessor\..文件夾中.

  1. ZooComponent注射器對象的創建
    ZooComponent依賴了ZooModule
final class DaggerZooComponent implements ZooComponent {
    private final ZooModule zooModule;
    public static ZooComponent create() {
        // 這裏最終調用的是Builder.build(),然後回創建ZooComponent對象.
        return new Builder().build();
    }
    static final class Builder {
        private Builder() {
        }
        public ZooComponent build() {
            if (zooModule == null) {
              // 依賴的ZooModule對象在此處創建
              this.zooModule = new ZooModule();
            }
            // DaggerZooComponent在這裏被創建,它持有zooModule引用,zooModule是一個工廠類,裏面提供了創建Tiger對象的方法.
            return new DaggerZooComponent(zooModule);
        }
    }
}
  1. DaggerPlaygroundComponent對象的創建
    DaggerPlaygroundComponent依賴DaggerZooComponent注射器
    • DaggerPlaygroundComponent.builder()
      創建DaggerPlaygroundComponent中的內部類Builder對象
       final class DaggerPlaygroundComponent implements PlaygroundComponent {
           public static Builder builder() {
               return new Builder();
           }
           static final class Builder {
               private Builder() {
               }
           }
       }
    
    • DaggerPlaygroundComponent.Builder.zooComponent(zooComponent)
      DaggerPlaygroundComponent.Builder對象設置zooComponent注射器對象.
       final class DaggerPlaygroundComponent implements PlaygroundComponent {
           private ZooComponent zooComponent;
           static final class Builder {
               // 爲Builder對象設置ZooComponent對象
               public Builder zooComponent(ZooComponent zooComponent) {
                 this.zooComponent = Preconditions.checkNotNull(zooComponent);
                 return this;
               }
           }
       }
    
    • DaggerPlaygroundComponent.Builder.build()
      創建DaggerPlaygroundComponent對象
       final class DaggerPlaygroundComponent implements PlaygroundComponent {
           static final class Builder {
               public PlaygroundComponent build() {
                   Preconditions.checkBuilderRequirement(zooComponent, ZooComponent.class);
                   // 創建DaggerPlaygroundComponent對象,它持有zooComponent引用
                   return new DaggerPlaygroundComponent(zooComponent);
               }
           } 
       }
    
  2. Playground對象注入Tiger對象
    DaggerPlaygroundComponent.inject(this)
final class DaggerPlaygroundComponent implements PlaygroundComponent {
    private final ZooComponent zooComponent;// ZooComponent注射器
    @Override
    public Playground inject(Playground zoo) {
        // playground被注入的容器
        return injectPlayground(zoo);
    }
    
    private Playground injectPlayground(Playground instance) {
        // zooComponent.providerTiger(): 獲取Tiger對象,這個就是在zooComponent注射器中定義的接口方法.具體的實現在DaggerZooComponent類中.
        // Playground_MembersInjector.injectTiger(instance,tiger): 具體賦值操作在這個地方.
        Playground_MembersInjector.injectTiger(instance, Preconditions.checkNotNull(zooComponent.providerTiger(), "Cannot return null from a non-@Nullable component method"));
        return instance;
    }
}
  1. 如何從依賴的注射器ZooComponent中獲取Tiger對象
    具體的實現在DaggerZooComponent中,DaggerZooComponent中持有ZooModule工廠類.
final class DaggerZooComponent implements ZooComponent {
    private final ZooModule zooModule;
    @Override
    public Tiger providerTiger() {
      // 接着向下看  
      return ZooModule_ProviderTigerFactory.providerTiger(zooModule);
    }
}
public final class ZooModule_ProviderTigerFactory implements Factory<Tiger> {
    // instance代表ZooModule工廠對象
    // providerTiger()方法就是在ZooModule類中用戶定義的方法了,該方法返回Tiger對象.
    public static Tiger providerTiger(ZooModule instance) {
      return Preconditions.checkNotNull(instance.providerTiger(), "Cannot return null from a non-@Nullable @Provides method");
    }
}
  1. Playground_MembersInjector.injectTiger(instance, zooComponent.providerTiger())
    Playground對象中所需字段賦值,instancePlayground對象,zooComponent.providerTiger()上面分析過是用來創建tiger對象的。
public final class Playground_MembersInjector implements MembersInjector<Playground> {
    public static void injectTiger(Playground instance, Object tiger) {
      // 最終的賦值操作在這裏
      instance.tiger = (Tiger) tiger;
    }
}

注射器之間的依賴唯一要注意的點是被依賴的注射器需要定義接口方法將自己需要提供的對象暴露給需要的注射器,案例中提供了Tiger providerTiger()接口方法用來暴露Tiger對象.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章