我有一个大型 Android 代码库,我正在编写一个自定义 lint 规则来检查某些属性的值是否在给定范围内。
例如,我有这个组件:
<MyCustomComponent
my:animation_factor="0.7"
...>
</MyCustomComponent>
我想编写一个 lint 规则,提醒开发人员注意 my:animation_factor
>= 1 的值应谨慎使用。
我按照 http://tools.android.com/tips/lint-custom-rules 中的说明进行操作并设法使用以下代码检索 my:animation_factor
的值:
import com.android.tools.lint.detector.api.*;
public class XmlInterpolatorFactorTooHighDetector {
....
@Override
public Collection<String> getApplicableElements() {
return ImmutableList.of("MyCustomComponent");
}
@Override
public void visitElement(XmlContext context, Element element) {
String factor = element.getAttribute("my:animation_factor");
...
if (value.startsWith("@dimen/")) {
// How do I resolve @dimen/xyz to 1.85?
} else {
String value = Float.parseFloat(factor);
}
}
}
当 my:animation_factor
等属性具有字面值(例如 0.7
)时,此代码可以正常工作。
但是,当属性值为资源时(例如 @dimen/standard_anim_factor
),则 element.getAttribute(...)
会返回属性的字符串值的实际解析值。
例如,当我有一个如下所示的 MyCustomComponent
时:
<MyCustomComponent
my:animation_factor="@dimen/standard_anim_factory"
...>
</MyCustomComponent>
和@dimen/standard_anim_factor
在别处定义:
<dimen name="standard_anim_factor">1.85</dimen>
然后字符串 factor
变为“@dimen/standard_anim_factor”而不是“1.85”。
有没有办法在处理 MyCustomComponent
元素时将“@dimen/standard_anim_factor”解析为资源的实际值(即“1.85”)?
最佳答案
值解析的一般问题是,它们取决于您所在的 Android 运行时上下文。可能有多个 values
文件夹,您的键 @dimen 具有不同的具体值/standard_anim_factory
,所以你知道。
不过,AFAIK 存在两种选择:
执行两阶段检测:
- 第 1 阶段:扫描您的资源
- 扫描您的属性并将其放入列表中(而不是立即对其进行评估)
- 扫描您的维度值并将它们也放入列表中
- 第 2 阶段:
- 覆盖
Detector.afterProjectCheck
并通过遍历阶段 1 中填充的两个列表来解析您的属性
通常
LintUtils
类 [1] 是处理这些东西的完美场所,但遗憾的是没有解决维度值的方法。但是,有一个名为getStyleAttributes
的方法演示了如何解析资源值。因此,您可以编写自己方便的方法来解析维度值:
private int resolveDimensionValue(String name, Context context){
LintClient client = context.getDriver().getClient();
LintProject project = context.getDriver().getProject();
AbstractResourceRepository resources = client.getProjectResources(project, true);
return Integer.valueOf(resources.getResourceItem(ResourceType.DIMEN, name).get(0).getResourceValue(false).getValue());
}
注意:我还没有测试过上面的代码。所以请将其视为理论建议:-)
只是对您的自定义 Lint 规则代码的一点小建议,因为您只对属性感兴趣:
而不是在 visitElement
中做这样的事情:
String factor = element.getAttribute("my:animation_factor");
...你可能想做这样的事情:
@Override
public Collection<String> getApplicableAttributes() {
return ImmutableList.of("my:animation_factor");
}
@Override
void visitAttribute(@NonNull XmlContext context, @NonNull Attr attribute){
...
}
但这只是一个偏好问题:-)
关于android - 在自定义 lint 规则中解析资源值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30357155/