Java Dagger找不到由其他批注处理器生成的类
我已经编写了一个简单的注释处理器(只是为了好玩),它将生成我在上一个项目中编写的一些样板代码。它实际上通过收集活动类的注释来生成如下模块Java Dagger找不到由其他批注处理器生成的类,java,android,dagger-2,annotation-processing,annotation-processor,Java,Android,Dagger 2,Annotation Processing,Annotation Processor,我已经编写了一个简单的注释处理器(只是为了好玩),它将生成我在上一个项目中编写的一些样板代码。它实际上通过收集活动类的注释来生成如下模块 @Module abstract class ActivityInjectorModule { @ContributesAndroidInjector abstract fun providesMain2Activity(): Main2Activity @ContributesAndroidInjector abstract fun pro
@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
}
}
@Singleton
@组成部分(
模块=[
AndroidInjectionModule::类,
AppModule::类,
ActivityInjectorModule::类
]
)
接口组件:AndroidJector
您可以看到生成的文件在同一个包中,但也引用了完全限定名。仍然匕首报告错误
如果有人想试验,这里是github存储库可能有一种更优雅的方法来解决这个问题,但最简单、最可靠的解决方案是使用javac
执行两次操作-一次只运行注释处理器,第二次执行它通常执行的所有操作
javac
指定了两个可以帮助您解决问题的选项
-proc:{none,only}
控制是否完成批注处理和/或编译-proc:none表示编译在没有注释处理的情况下进行-proc:only表示只进行注释处理,不进行任何后续编译
-处理器类别1[,类别2,类别3…]
要运行的批注处理器的名称。这将绕过默认的发现过程
第一步(仅运行您自己的注释处理器)是
第二步(常规构建)是
如果您使用的是Ant或Maven之类的工具,那么您应该能够更新构建指令,使其具有两个编译器过程,并且只需付出最小的努力
编辑:下面是我对Gradle指令的尝试
我对Gradle没有经验,但看起来你需要这样做
在Gradle构建脚本中,需要定义预处理任务,并将对任务的依赖项添加到javaCompile任务中
javaCompile.dependsOn myAnnotationTask
task myAnnotationTask(type: JavaCompile) {
options.compilerArgs << '-proc:only' << '-processors com.foo.bar.MyAnnotationProcessor'
}
javaCompile.dependsOn myAnnotationTask
任务myAnnotationTask(类型:JavaCompile){
options.compilerArgs新答案
不知何故,我没有注意到您正在使用kapt。如果您将其添加到构建中,kapt可以处理您的类,即使没有完整的限定名(这很了不起)。gradle:
kapt {
arguments {
arg("argumentIncremental", 'true')
}
correctErrorTypes = true
}
更多信息:
前面的答案可能有用,因为有人在gradle中与annotationProcessor(apt)有相同的问题
简短回答:为ActivityInjectorModule使用完全限定名称:
@dagger.Component(modules = {dagger.android.AndroidInjectionModule.class, com.mallaudin.daggietest.di.AppModule.class, com.mallaudin.daggietest.di.ActivityInjectorModule.class})
或者将两个文件放在同一个包中
长答案:Dagger是一个注释处理器,它在编译代码之前运行,并且(可能)在其他注释处理器运行之前运行。处理器运行的顺序没有定义
Dagger annotation processor将处理用@Dagger.Component注释的TypeElement,并尝试查找包括“ActivityInjectorModule.class”在内的所有模块。问题是,ActivityInjectorModule可能尚未生成。因此,“ActivityInjectorModule”此时将没有包。Dagger将假定ActivityInjectorModule与组件类驻留在同一个包中,并且不会添加导入。通常的解决方法是为生成的类使用全名,如果其他批注处理器使用这些类。有时移动批注进程是有意义的向差异渐变模块唱歌,但我不认为这是您想要的。解决方案:
生成java代码。Kapt
在尽可能早的一轮中写入生成的文件
说明:
Javac
annotation processor使用轮而不是定义处理器顺序。因此,通常简化算法如下:
收集所有java源代码
运行所有批注处理器。任何批注处理器都可以使用生成新文件
收集所有生成的文件,如果有,再次运行步骤2
如果没有生成文件,则再运行一轮,返回true
,表示这是最后一轮
现在有一点关于kapt
kapt
来运行注释处理器。为了使之成为可能,它首先运行kotlin compliler并在它们上运行javac
。目前kapt
,这意味着它不会为注释处理器生成的kotlin类生成java存根。
注意:javac
仍然使用多轮,它无法获取生成的kotlin源。
回到你的问题上来,一个可能的选择是将生成的类移动到一个单独的模块中,就像
但最简单的选择是直接生成java代码,生成的java类将由javac
自动获取,启动第二轮注释处理,dagger将在其中处理它们
再多说几句:
- 不要在
RoundEnvironment.processingOver()==true
时生成代码,它不会触发另一轮。在看到注释的同一轮中生成代码
- 要使生成的代码对注释处理器可见,请使用编写它
你能分享你的应用程序类或者你定义所有模块的地方吗?@ShwetaChauhan我已经更新了代码。请看一看。应用程序类扩展DaggerApplication()对吗?我已经在做了。实际上我已经搜索了很多关于这个的信息
javaCompile.dependsOn myAnnotationTask
task myAnnotationTask(type: JavaCompile) {
options.compilerArgs << '-proc:only' << '-processors com.foo.bar.MyAnnotationProcessor'
}
kapt {
arguments {
arg("argumentIncremental", 'true')
}
correctErrorTypes = true
}
@dagger.Component(modules = {dagger.android.AndroidInjectionModule.class, com.mallaudin.daggietest.di.AppModule.class, com.mallaudin.daggietest.di.ActivityInjectorModule.class})