Dagger 2 生成代码中 proxyProvide 的用途
Purpose of proxyProvide in 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()
方法?一个不能叫另一个吗?
(顺便说一下,我确实意识到我不再需要在我的应用资产中捆绑字体。这不是这里的问题。)
首先:Dagger 生成此代码 ahead-of-time 以便在模块化构建中获得更好的构建性能。因此,我们不知道 which (或两者,或两者都不需要),所以我们生成两者以防万一,并假设 Proguard 将能够剥离任何东西未使用。
那么两者到底在做什么呢?
第一个(get()
方法)在请求此工厂表示的绑定作为 Provider<T>
时调用。这可以直接发生,或者如果绑定是作用域的,或者其他一些场景。
第二种情况就是我们所说的内联。假设您在模块中有一个 @Provides
方法,并且您的 @Component
上有一个 returns 该类型的方法。最理想的生成代码如下:
@Override
public YourBinding y() {
return YourModule.yourProvidesMethod();
}
事实是,provides 方法可能无法从与您的组件相同的包中访问,因此我们生成了这个 "proxy" 方法,它为 Dagger 提供了正确的可访问性。它还使该方法的所有参数都可访问,必要时将它们擦除为 Object
。如果它们确实被擦除(将其视为通用类型擦除),我们需要将强制转换插入正确的类型 inside 代理方法。
Provider.get()
实现不需要它,因为调用它的代码应该可以访问所有类型。
总而言之 - 我们想要生成两个版本,希望您只使用一个版本,Proguard 应该清理另一个版本。
希望对您有所帮助!
我有这个 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()
方法?一个不能叫另一个吗?
(顺便说一下,我确实意识到我不再需要在我的应用资产中捆绑字体。这不是这里的问题。)
首先:Dagger 生成此代码 ahead-of-time 以便在模块化构建中获得更好的构建性能。因此,我们不知道 which (或两者,或两者都不需要),所以我们生成两者以防万一,并假设 Proguard 将能够剥离任何东西未使用。
那么两者到底在做什么呢?
第一个(get()
方法)在请求此工厂表示的绑定作为 Provider<T>
时调用。这可以直接发生,或者如果绑定是作用域的,或者其他一些场景。
第二种情况就是我们所说的内联。假设您在模块中有一个 @Provides
方法,并且您的 @Component
上有一个 returns 该类型的方法。最理想的生成代码如下:
@Override
public YourBinding y() {
return YourModule.yourProvidesMethod();
}
事实是,provides 方法可能无法从与您的组件相同的包中访问,因此我们生成了这个 "proxy" 方法,它为 Dagger 提供了正确的可访问性。它还使该方法的所有参数都可访问,必要时将它们擦除为 Object
。如果它们确实被擦除(将其视为通用类型擦除),我们需要将强制转换插入正确的类型 inside 代理方法。
Provider.get()
实现不需要它,因为调用它的代码应该可以访问所有类型。
总而言之 - 我们想要生成两个版本,希望您只使用一个版本,Proguard 应该清理另一个版本。
希望对您有所帮助!