解析自定义lint规则中的资源值

时间:2015-05-20 18:02:11

标签: android lint android-lint

我有一个很大的Android代码库,我正在编写一个自定义lint规则,用于检查某些属性的值是否在给定范围内。

例如,我有这个组件:

<MyCustomComponent
    my:animation_factor="0.7"
    ...>
</MyCustomComponent>

我想编写一个lint规则,提醒开发人员谨慎使用my:animation_factor&gt; = 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变为&#34; @ dimen / standard_anim_factor&#34;而不是&#34; 1.85&#34;。

有没有办法解决&#34; @ dimen / standard_anim_factor&#34;处理MyCustomComponent元素时,资源的实际价值(即&#34; 1.85&#34;)?

3 个答案:

答案 0 :(得分:0)

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

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

答案 1 :(得分:0)

在解析数据后假设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);

}

答案 2 :(得分:0)

值解析的一般问题是,它们取决于您所在的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
  2. 对于您的自定义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){
        ...
    }
    

    但这只是一个偏好问题: - )