【问题标题】:Resolving resource values in custom lint rule解析自定义 lint 规则中的资源值
【发布时间】:2015-05-20 18:02:10
【问题描述】:

我有一个庞大的 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”)?

【问题讨论】:

  • 无法理解您的问题,如果您获得价值0.7,那么它为什么指向standard_anim_factor,或者如果它指向它,问题是什么?
  • 感谢您指出这一点。我编辑了问题以使其更具可读性。

标签: android lint android-lint


【解决方案1】:

值解析的一般问题是,它们取决于您所在的 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());
    }

注意:我还没有测试过上面的代码。所以请将其视为理论建议:-)

  1. https://android.googlesource.com/platform/tools/base/+/master/lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/LintUtils.java

对您的自定义 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 没有更好的界面(或只有更好的模板)来执行此操作。
【解决方案2】:

我相信您正在寻找getResources().getDimension()。

来源:http://developer.android.com/reference/android/content/res/Resources.html#getDimension%28int%29

【讨论】:

  • 问题是 getResources() 是 android.content.Context 的一个方法,但 Lint 使用的 com.android.tools.lint.detector.api.Context 没有获取/解析资源的方法。
【解决方案3】:

解析你的数据后假设xml节点,试试下面的

Element element = null; //It is your root node.
NamedNodeMap attrib = (NamedNodeMap) element;

int numAttrs = attrib.getLength ();

for (int i = 0; i < numAttrs; i++) {
    Attr attr = (Attr) attrib.item (i);

    String attrName = attr.getNodeName ();
    String attrValue = attr.getNodeValue ();

    System.out.println ("Found attribute: " + attrName + " with value: " + attrValue);

}

【讨论】:

  • 感谢 Murtaza 但这只是打印 Found attribute: my:animation_factor with value: @dimen/standard_anim_factory 这是我已经拥有的...我希望它打印 Found attribute: my:animation_factor with value: 1.85。
  • 这意味着你需要重申它,希望你明白我想说什么。如果您找到了该节点,则重复该元素。
猜你喜欢
  • 1970-01-01
  • 2014-10-30
  • 1970-01-01
  • 2021-03-17
  • 2013-05-20
  • 2019-09-25
  • 2017-02-16
  • 2014-12-23
  • 2022-01-23
相关资源
最近更新 更多