代理的目的提供Dagger 2生成的代码

时间:2018-01-22 11:51:26

标签: java android dagger-2 generated-code

我有这个Dagger模块。我想了解生成的代码,以便验证我的Dagger配置是否最佳。

@Module
public class TypefaceModule {

    @Provides @Singleton @Named("Roboto Light")
    static Typeface provideRobotoLight(AssetManager assets) {
        return Typeface.createFromAsset(assets, "fonts/Roboto-Light.ttf");
    }

}

这里是生成的代码(Dagger 2.14.1):

public final class TypefaceModule_ProvideRobotoLightFactory implements Factory<Typeface> {
  private final Provider<AssetManager> assetsProvider;

  public TypefaceModule_ProvideRobotoLightFactory(Provider<AssetManager> assetsProvider) {
    this.assetsProvider = assetsProvider;
  }

  @Override
  public Typeface get() {
    return Preconditions.checkNotNull(
        TypefaceModule.provideRobotoLight(assetsProvider.get()),
        "Cannot return null from a non-@Nullable @Provides method");
  }

  public static TypefaceModule_ProvideRobotoLightFactory create(
      Provider<AssetManager> assetsProvider) {
    return new TypefaceModule_ProvideRobotoLightFactory(assetsProvider);
  }

  public static Typeface proxyProvideRobotoLight(AssetManager assets) {
    return Preconditions.checkNotNull(
        TypefaceModule.provideRobotoLight(assets),
        "Cannot return null from a non-@Nullable @Provides method");
  }
}

有两个函数几乎完全相同:实例方法get()和静态方法proxyProvideRobotoLight()

为什么Dagger生成了这个代码的两个版本,它们都静态调用模块的provide()方法?一个人不能打电话给对方吗?

(顺便说一句,我确实意识到我不再需要在我的应用资产中捆绑字体。这不是问题所在。)

1 个答案:

答案 0 :(得分:4)

首先:Dagger提前生成此代码,以便在模块化构建中获得更好的构建性能。因此,我们不知道哪个(或两者,或两者都不需要),所以我们生成两者以防万一,并假设Proguard能够剥离任何东西未使用的。

那么两者究竟在做什么?

当此工厂表示的绑定被请求为get()时,将调用第一个(Provider<T>方法)。这可以直接发生,或者如果绑定是作用域,或者其他一些场景。

第二种情况是我们称之为内联。假设您在模块中有@Provides方法,并且您的@Component上有一个返回该类型的方法。生成的最理想代码是:

@Override
public YourBinding y() {
  return YourModule.yourProvidesMethod();
}

问题是,提供的方法可能无法从与组件相同的包中访问,因此我们生成了这个&#34;代理&#34;使Dagger具有正确的可访问性的方法。它还可以访问该方法的所有参数,必要时将它们删除到Object。如果它们被删除(将其视为泛型类型擦除),我们需要将强制转换插入内部代理方法中的正确类型。

Provider.get()实现并不需要它,因为在那里,所有类型都应该由调用它的代码访问。

总而言之 - 我们希望生成两个版本,希望您只使用一个版本,而Proguard应该清理另一个版本。

希望有所帮助!