java - Dagger 找不到其他注解处理器生成的类
问题描述
我编写了一个简单的注释处理器(只是为了好玩),它将生成一些我在以前的项目中编写的样板代码。它实际上通过收集 Activity 类上的注释来生成如下所示的模块
@Module
abstract class ActivityInjectorModule {
@ContributesAndroidInjector
abstract fun providesMain2Activity(): Main2Activity
@ContributesAndroidInjector
abstract fun providesMainActivity(): MainActivity
}
但是,当我使用 dagger 运行它时,dagger 似乎无法找到由我的注释处理器生成的类。虽然类已生成并存在于生成的目录中,但我可以在我的源代码中使用它,但在编译时,dagger 会产生以下异常。有什么专家建议吗?
error: cannot find symbol
@dagger.Component(modules = {dagger.android.AndroidInjectionModule.class, com.mallaudin.daggietest.di.AppModule.class, ActivityInjectorModule.class})
^
symbol: class ActivityInjectorModule
这是主要的应用程序组件。
@Singleton
@Component(
modules = [
AndroidInjectionModule::class,
AppModule::class,
ActivityInjectorModule::class
]
)
interface AppComponent : AndroidInjector<App> {
@Component.Builder
interface Builder {
fun addContext(@BindsInstance ctx: Context): Builder
fun build(): AppComponent
}
}
ActivityInjectorModule类由注解处理器生成,存在于生成目录中。
应用类
class App : DaggerApplication() {
override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
return DaggerAppComponent.builder().addContext(this).build()
}
}
如果我自己创建生成的类,一切都会完美运行。在编译时不知何故,当我的注释处理器生成时,dagger 无法找到该类。
在 Yuriy Kulikov 的回答之后,
您可以看到生成的文件在同一个包中,但也使用完全限定名称引用。仍然匕首报告错误。
如果有人想进行实验,这里是github 存储库的链接
解决方案
解决方案:
- 生成java代码。
Kapt
不支持多轮。 - 在尽可能早的回合写入生成的文件。
解释:
Javac
注释处理器使用轮次而不是定义处理器顺序。所以通常简化的算法是这样的:
- 收集所有 java 源
- 运行所有注释处理器。任何注释处理器都可以使用Filer生成新文件。
- 收集所有生成的文件,如果有,请再次运行第 2 步。
- 如果没有生成文件,则在RoundEnvironment.processingOver()返回的地方再运行一轮
true
,表示这是最后一轮。
现在稍微介绍一下kapt
。Kapt
使用 javac运行注释处理器。为了使它成为可能,它首先运行 kotlin 编译器以生成 java 存根文件并javac
在它们上运行。目前kapt
不支持多轮,这意味着它不会为注释处理器生成的 kotlin 类生成 java 存根。
注意:javac
仍然使用多轮,它只是无法拾取生成的 kotlin 源。
所以,回到你的问题。一种可能的选择是将生成的类移动到一个单独的模块中,就像这里描述的那样。
但最简单的选择是直接生成 java 代码,您生成的 java 类将被自动拾取javac
,启动第二轮注释处理,dagger 将在其中处理它们。
还有一些注意事项:
- 时不要生成你的代码
RoundEnvironment.processingOver() == true
,它不会触发另一轮。在您看到注释的同一轮中生成它。 - 要使生成的代码对注释处理器可见,请使用Filer编写它。
推荐阅读
- r - r 如何根据 Pr 值从 r 摘要(模型)中选择截距/变量
- python - ModuleNotFoundError:没有名为“samples.coco”的模块
- python-3.x - python3在命令中插入变量值
- react-native - BackHandler.exitApp() 时重置 Linking.getInitialURL()
- javascript - 我如何知道 Vue 应用程序是否是从 javascript 安装的?
- java - 杰克逊:反序列化 JSON 提取深度属性到父类
- python - 如何从一个文件中提取特定数据并将其添加到特定位置的另一个文件中?
- firebase - 使用 Cloud Firestore 更新数组中的数据
- ios - iOS:调用 AWS Amplify GET 时出现 IncompleteSignatureException
- algorithm - 对相邻值之间的增量进行编码的数据结构/编码是否有名称?