Java 在Dagger 2生成的代码中提供代理的目的

Java 在Dagger 2生成的代码中提供代理的目的,java,android,dagger-2,generated-code,Java,Android,Dagger 2,Generated Code,我有这个匕首模块。我想了解生成的代码,以便验证我的匕首配置是否最优 @模块 公共类字体模块{ @提供@Singleton@Named(“Roboto Light”) 静态字体提供程序Bobotlight(AssetManager资产){ 返回Typeface.createFromAsset(资产,“字体/Roboto-Light.ttf”); } } 以下是生成的代码(Dagger 2.14.1): public final class TypefaceModule\u provider机器人

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

@模块
公共类字体模块{
@提供@Singleton@Named(“Roboto Light”)
静态字体提供程序Bobotlight(AssetManager资产){
返回Typeface.createFromAsset(资产,“字体/Roboto-Light.ttf”);
}
}
以下是生成的代码(Dagger 2.14.1):

public final class TypefaceModule\u provider机器人灯光工厂实现工厂{
私人最终提供者资产提供者;
公共字体模块\u提供程序BobotLightFactory(提供程序资产提供程序){
this.assetsProvider=assetsProvider;
}
@凌驾
公共字体get(){
返回前提条件。checkNotNull(
TypefaceModule.ProviderRobotLight(AssetProvider.get()),
“无法从非@Nullable@Provides方法返回null”);
}
公共静态字体模块\u ProviderRobotLightFactory创建(
提供者资产(提供者){
返回新的字体模块\u ProviderBobotLightFactory(AssetProvider);
}
公共静态字体ProxyProviderRobotolight(资产管理器资产){
返回前提条件。checkNotNull(
字体模块。ProviderBobotLight(资产),
“无法从非@Nullable@Provides方法返回null”);
}
}
有两个函数可以做几乎相同的事情:实例方法
get()
,和静态方法
proxyProviderRobotolight()

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


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

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

那么,这两个人实际上在做什么呢?

第一个方法(get()方法)是在将此工厂表示的绑定请求为
提供程序时调用的。这种情况可以直接发生,也可以在绑定范围限定的情况下发生,或者在其他一些情况下发生

第二种情况我们称之为内联。假设模块中有一个
@Provides
方法,并且
@组件上有一个返回该类型的方法。要生成的最理想代码如下所示:

@Override
public YourBinding y() {
  return YourModule.yourProvidesMethod();
}
问题是,提供的方法可能无法从与组件相同的包中访问,因此我们生成了这个“代理”方法,它为Dagger提供了正确的可访问性。它还可以访问该方法的所有参数,如有必要,可将其擦除到
对象
。如果它们确实被擦除了(就像泛型类型擦除一样),我们需要在代理方法中插入正确类型的强制转换

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

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


希望有帮助

很好的观察和有趣的问题。似乎我们需要dagger团队的人来回答这个问题。由于方法是静态的,所以在这两种情况下(
.get
.proxyProvider
)都是在不使用模块实例的情况下调用的,否则
get
将使用通过构造函数传递和存储的引用(包括模块实例)而
proxyProvider
希望所有必需的细节都作为参数传递。假设还有改进的余地,即在生成的代码中检测并重用静态方法。@AivarasPrudnikovas您是否愿意将其作为一个答案写出来,可能显示了一些如何以不同方式调用它们的示例?因此,这些
provideProxy
方法的唯一目的是在模块位于另一个包中时获得访问权限。此外,如果我们既不添加范围注释也不直接请求
提供程序
,Dagger是否不在内部使用
提供程序
?如果需要对任何参数进行空检查,也会使用它们。在许多情况下,它们都会被使用。如果绑定是由另一个需要提供程序的类型请求的(出于您提到的原因),也会使用提供程序。因此,如果您有A->B->C,A的作用域是A,B和C将有提供程序实例谢谢您的澄清。在Dagger的早期版本中,所有调用都是从
Provider
s返回的,而在较新版本中,大多数调用都是内联的,以提高代码的效率。对吗?在一个没有我创建的范围的非常简单的场景中,没有任何
\u工厂
被实例化为
提供者