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

Gra*_*and 13 java android generated-code dagger-2

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

@Module
public class TypefaceModule {

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

}
Run Code Online (Sandbox Code Playgroud)

这是生成的代码(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");
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

小智 5

首先,Dagger会提前生成此代码,因此在模块化构建中,您可以获得更好的构建性能。因此,我们不知道您将需要哪个(或两者,或都不需要),因此我们生成这两个参数只是为了以防万一,并假设Proguard将能够剥离所有未使用的东西。

那么,两者实际上都在做什么呢?

get()当将此工厂表示的绑定请求为时,将调用第一个(方法)Provider<T>。这可以直接发生,也可以在绑定范围内发生,也可以在其他一些情况下发生。

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

@Override
public YourBinding y() {
  return YourModule.yourProvidesMethod();
}
Run Code Online (Sandbox Code Playgroud)

事实是,provider方法可能无法从与您组件相同的包中访问,因此我们生成了此“ proxy”方法,该方法为Dagger提供了正确的可访问性。它还使该方法的所有参数都可以访问,并Object在必要时将其删除。如果他们得到清除(认为这就像泛型类型擦除),我们需要再插入铸件正确类型的代理方法。

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

综上所述-我们想生成两个版本,希望您只使用其中一个,而Proguard应该清除另一个版本。

希望有帮助!