资源$ NotFoundException:资源ID无效。为什么?

时间:2013-03-27 01:18:25

标签: android android-resources

我正在尝试向我的dimens.xml文件中添加一个浮点数。

我正在阅读following SO answer。当我尝试解决方案时,我得到了评论中描述的异常。我试图找出为什么抛出异常。

为了完整性,这里是XML:

<item name="zoom_level" format="float" type="dimen">15.0</item>

这是爆炸的代码:

final float zoom = this.getResources().getDimension(R.dimen.zoom_level);

我跳进了Android源代码,这里是getDimension的方法定义:

public float getDimension(int id) throws NotFoundException {
    synchronized (mTmpValue) {
        TypedValue value = mTmpValue;
        getValue(id, value, true);
        if (value.type == TypedValue.TYPE_DIMENSION) {
            return TypedValue.complexToDimension(value.data, mMetrics);
        }
        throw new NotFoundException(
                "Resource ID #0x" + Integer.toHexString(id) + " type #0x"
                + Integer.toHexString(value.type) + " is not valid");
    }
}

所以无论出于何种原因value.type != TypedValue.TYPE_DIMENSION。我没有完全设置Android源代码,因此我无法在其中轻松添加Log.w("YARIAN", "value type is " + value.type)'语句。

然后我跳进了getValue,调用链似乎是:

Resources.getValue -> AssetManager.getResourceValue -> AssetManager.loadResourceValue

loadResourceValue是一种本地方法,这是我的挖掘分崩离析的地方。

任何人都知道了解最新情况的最佳方式是什么?


我还注意到Resources有一个TypedValue.TYPE_FLOATTypedValue.TYPE_DIMENSION。但是在XML中,我不能写type="float"

评论中描述的工作是使用type=string,然后使用Float.parse来获取浮动。这有必要吗?为什么或为什么不呢?

4 个答案:

答案 0 :(得分:15)

我知道这是一个迟到的答案,但你应该使用TypedValue#getFloat()而不是像你建议的那样将字符串解析为浮点数。

XML:

    <item name="float_resource" format="float" type="raw">5.0</item>

爪哇:

TypedValue out = new TypedValue();
context.getResources().getValue(R.raw.float_resource, out, true);
float floatResource = out.getFloat();

如果您愿意,可以将fractionrawstring作为type,这仅对应R中的资源类。

答案 1 :(得分:2)

我也遇到了这个问题,虽然错误消息不是很有帮助,但我意识到我的问题是我在资源文件中只放了一个浮动值并且没有指定测量值。例如,将15.0切换到15.0dp可以避免此问题,并允许您仍然使用常规维度资源。

答案 2 :(得分:1)

现在有Resources.getFloat(来自API 29)和ResourcesCompat.getFloat

val zoomLevel: Float = ResourcesCompat.getFloat(resources, R.dimen.zoom_level)

您可以保留问题中的zoom_level XML。

答案 3 :(得分:0)

Kotlin扩展功能由Rich答案制成:

fun Resources.getFloatValue(@DimenRes floatRes:Int):Float{
    val out = TypedValue()
    getValue(floatRes, out, true)
    return out.float
}

用法:

resources.getFloatValue(R.dimen.my_float)