我正在为Android构建一个Annotation Processor(为了将来的解释,我们称之为TestProcessor
)。
该计划是让处理器在两种模式下运行:
-
Mode 1
:代码的生成A
-
Mode 2
:生成代码A
和B
Mode 2
仅当处理器为其生成代码的环境中存在附加(可选)包时才应选择。
如果可选包存在,是否有办法在Annotation Processor的process
方法中找到?
编辑1:
关于"(可选)一揽子计划"的小说明。我所说的附加包是指可能但不必存在于项目中(即使用处理器)的java包。例如,可选包可以表示外部库中的内容。外部库可以但不必包含在项目中。
让我举一个小例子:
- 让我们假设我们有一个(一个模块)项目
Sample
Sample
正在使用我的TestProcessor
- 让我们以
Square's
Picasso
作为外部库的示例 - 如果
Sample
将Square's
Picasso
作为其依赖项之一,则TestProcessor
在Mode 2
中操作,并生成代码A
和B
。换句话说:如果您可以毫无问题地使用com.square.picasso
(在Sample
中)中的类,那么处理器应该在Mode 2
中运行 - 如果
Sample's
依赖项中没有Square's
Picasso
,则TestProcessor
在Mode 1
中操作,仅生成代码A
编辑2:
我想了两个解决这个问题的方法:
- 对两个
processor
Modes
使用两种类型的注释(例如:@DoStuffModeOne
、@DoStuffModeTwo
) - 使用触发
Mode 2
使用的第二种类型的注释(例如应在Application
上使用)(例如:@TriggerModeTwo
)
在我的情况下,第二种解决方法要好得多,但仍然比TestProcessor
本身可以决定选择哪个Mode
的情况差得多。
您可以在应用程序的类路径中检查其中一个ButterKnife
类。然后根据检查结果执行逻辑。
Class butterKnifeClass = null;
try {
butterKnifeClass = Class.forName("butterknife.ButterKnife");
} catch (ClassNotFoundException e) {
// no butterknife present
}
if (butterKnifeClass != null) {
// blah... stuff with butterknife
}
您可以使用此代码来确定注释处理环境中是否存在类。
TypeElement typeElement = processingEnvironment.getElementUtils().
getTypeElement("com.squareup.picasso.Picasso");
我没有成功地使用Elements.getPackageElement()
方法,因为它成功地返回了不存在的包(至少在Eclipse下是这样),并且在这样创建的包上运行PackageElement.getEnclosedElements()
方法是空的,即使对于非空包也是如此。我建议您像前面的例子一样,在您感兴趣的包中选择一个特定的类,因为它对现有类型元素起到了预期的作用,而对不存在的类型返回null
。
我目前找不到基于Annotation Processing API的方法来决定以这种方式找到的类型元素是基于项目源路径上的源代码文件,还是基于编译类路径上的二进制类文件 我希望这能有所帮助。
除了JBirdVegas建议的解决方案之外;此函数可用于在运行时检查外部库中是否存在包。
public static boolean packageExists(String packagePath) {
return Thread.currentThread().getContextClassLoader().getResource(packagePath) != null;
}
用法:
packageExists("apackage/innerpackage")