带注解传值时获取Android R class?

Get Android R class when passing value with annotation?

我有这个注释BindPrefRes.class

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.SOURCE)
public @interface BindPrefRes {
    @StringRes int value();
}

现在,当我像这样在任何 Android 项目中使用该注释时:

@BindPrefRes(R.string.app_name) String appName;

我正在尝试使用 javax.annotation.processing.AbstractProcessor

获取值
int value = element.getAnnotation(BindPrefRes.class).value()

我得到了实际的 int (2131230753),我知道这是预期的行为。但是我如何将这个 int 解析回字段 (R.string.app_name),或者至少是该字段的字符串表示形式 ("R.string.app_name")?

source code is on GitHub 如果我不清楚。

简短回答:您应该尽可能避免这样做,因为可能根本无法获得所需的信息。例如,如果 Gradle(或其他构建系统)开始支持带有注解处理器的增量构建,那么在处理器运行时,R class 可能不会出现在编译路径上。

长答案:有两种方法:

  1. 扫描源码获取R classes
  2. 迭代找到的每个字段 R classes 并将所有常量添加到 Map
  3. 将从注释接收的值与来自地图的常量相关联

One implementation 这种方法(出于某种原因依赖于非 public Javac 内部结构)可以在 ButterKnife 资源中找到)。

Another one 由 Android Annotations 项目维护(您可以通过将处理器设为 Android Annotations 处理器的插件来复制或直接访问它)。

也丑

使用 Oracle 专有的半稳定树 API 直接内省 @BindPrefRes(R.string.app_name) 的源代码。我建议尽可能采用这种方法,因为它的副作用更少。

Obtain a TreePath注解值,转成ExpressionTree,手动解析内容