(六) Dagger2 @Module分析四

代碼示例
class Food {
}
class Tiger {
    // 假如老虎需要食物
    Food food;
    public Tiger(Food food) {
        this.food = food;
    }
    public void sleep() {
        System.out.println("Tiger sleeping");
    }
}

// 爲注射器提供工廠類
// @Module: 表示Dagger2可以將該類當作對象工廠.
@Module
class ZooModule {
    private Food food;
    public ZooModule(Food food) {
        this.food = food;
    }
    // @Provides: 表示Dagger2可以調用providerTiger(Food food)方法爲注射器提供對象.
    @Provides
    public Tiger providerTiger() {
        return new Tiger(food);
    }
}
// 對象使用者
public class Zoo {
    // @Inject: 該註解用於成員變量上代表注射器可以爲該成員變量賦值對象.
    @Inject
    Tiger tiger;

    @Test
    public void 案例六() {
        // ZooModule中的成員food無法通過Dagger2自動生成,需要用戶手動創建.
        DaggerZooComponent.builder().zooModule(new ZooModule(new Food())).build().inject(this);
        tiger.sleep();
    }
}
// 注射器
// @Component: 該註解是用來創造對象提供方和對象使用間的橋樑,如何將對象賦值給使用者的成員變量都是由它來做的.
@Component(modules = {ZooModule.class})
interface ZooComponent {
    Zoo inject(Zoo zoo);
}
Dagger2生成代碼閱讀

主要分析Module中依賴某個無法使用Dagger2創建的對象,該如何將該對象加入注射器中?
類似情況很常見,比如Activity由系統創建,假如某個Module依賴Activity對象,那Dagger2如何處理它們的依賴關係.

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

  1. DaggerZooComponent.builder().zooModule(new ZooModule(new Food())).build()
    創建DaggerZooComponent對象,這裏主要看下zooModule(new ZooModule(new Food()))如何處理的.
final class DaggerZooComponent implements ZooComponent {
    // 工廠對象
    private final ZooModule zooModule;
    // DaggerZooComponent構造方法
    private DaggerZooComponent(ZooModule zooModuleParam) {
        this.zooModule = zooModuleParam;
    }
    public static Builder builder() {
        // 創建DaggerZooComponent.Builder對象
        return new Builder();
    }
    static final class Builder {
        private ZooModule zooModule;
        private Builder() {
        }
        // 創建ZooModule對象
        public Builder zooModule(ZooModule zooModule) {
          this.zooModule = Preconditions.checkNotNull(zooModule);
          return this;
        }
        public ZooComponent build() {
          Preconditions.checkBuilderRequirement(zooModule, ZooModule.class);
          // 創建DaggerZooComponent對象,它持有ZooModule引用
          return new DaggerZooComponent(zooModule);
        }
    }
}
  1. .inject(this)對象注入
    使用DaggerZooComponent對象將Dagger2創建的Tiger對象注入到Zoo中.
final class DaggerZooComponent implements ZooComponent {
    // 接口中的方法,由DaggerZooComponent實現,該方法就是用來向Zoo對象中注入Tiger對象的.
    @Override
    public Zoo inject(Zoo zoo) {
        // zoo就是inject(this)中的this了,代表Zoo對象.
        return injectZoo(zoo);
    }
    private Zoo injectZoo(Zoo instance) {
        // 1. ZooModule_ProviderTigerFactory.providerTiger(zooModule): 通過ZooModule工廠獲取Zoo需要的Tiger對象.
        // 2. Zoo_MembersInjector.injectTiger(instance, getTiger()): 這裏就是爲Zoo對象中所需字段賦值.
        Zoo_MembersInjector.injectTiger(instance, ZooModule_ProviderTigerFactory.providerTiger(zooModule));
        return instance;
    }
}
  1. ZooModule_ProviderTigerFactory.providerTiger(zooModule)
public final class ZooModule_ProviderTigerFactory implements Factory<Tiger> {
    public static Tiger providerTiger(ZooModule instance) {
      // providerTiger()爲用戶在ZooModule中實現的方法,用來返回Tiger對象.
      return Preconditions.checkNotNull(instance.providerTiger(), "Cannot return null from a non-@Nullable @Provides method");
    }
}
  1. 賦值
    Zoo_MembersInjector.injectTiger(instance, ZooModule_ProviderTigerFactory.providerTiger(zooModule));
public final class Zoo_MembersInjector implements MembersInjector<Zoo> {
   public static void injectTiger(Zoo instance, Object tiger) {
     instance.tiger = (Tiger) tiger;
   } 
}

如果Foot無法通過Dagger2自行創建加入注射器中的話,可以用戶手動創建一個Foot對象,再通過Module構造將該對象傳入Module中,然後交給Module工廠方法使用.

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