UnsupportedOperationException: Failed to resolve attribute at index 13: TypedValue{t=0x2/d=0x7f03006

现象:使用到自定义属性时崩溃。
崩溃log:

08-31 14:44:49.382 E/AndroidRuntime(12381): Caused by: java.lang.UnsupportedOperationException: Failed to resolve attribute at index 13: TypedValue{t=0x2/d=0x7f030063 a=-1}
08-31 14:44:49.382 E/AndroidRuntime(12381): 	at android.content.res.TypedArray.getDrawableForDensity(TypedArray.java:946)
08-31 14:44:49.382 E/AndroidRuntime(12381): 	at android.content.res.TypedArray.getDrawable(TypedArray.java:930)
08-31 14:44:49.382 E/AndroidRuntime(12381): 	at android.view.View.<init>(View.java:5010)
08-31 14:44:49.382 E/AndroidRuntime(12381): 	at android.view.ViewGroup.<init>(ViewGroup.java:659)
08-31 14:44:49.382 E/AndroidRuntime(12381): 	at android.widget.RelativeLayout.<init>(RelativeLayout.java:248)

通用解决办法:LayoutInflater.from(context)中的context用activity的context或者当前view的context。(ps:后面会讲到针对于我这边应用的3种解决办法)下面我们来分析下问题。

自定义主题

我们想要应用的主题风格style可以整体变化,也就是Android手机上见到的换肤,它包括常见控件的Button、TextView和Dialog等的适配,这是我们的初衷。

自定义属性

我们知道想要主题风格变化,还需要自定义一些属性集declare-styleable和属性attr(说到重点啦,这就是我们出问题的地方)我们知道自定义属性一般如下三个步骤:

  1. 在values/attrs.xml中自定义属性名,如:
<attr name="element_tcl_navigation_item_bg_select" format="reference" />
  1. 在values/styles.xml的自定义主题中指定当前主题的自定义属性默认值,如:
<style name="UI_5_AppTheme" parent="DefaultAppTheme">
	<item name="element_tcl_navigation_item_bg_select">@drawable/element_tcl_navigation_item_bg_select</item>
</style>
  1. 在xml布局element_tcl_layout_navigation_item.xml(或Java代码)中使用自定义属性,以及使用xml文件,如:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rl_element_navigation_item_background"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="?attr/element_tcl_navigation_item_bg_select"/>
View view = LayoutInflater.from(context).inflate(R.layout.element_tcl_layout_navigation_item, this, true);

暴露问题

加载布局时,使用的是应用程序上下文,如:LayoutInflater.from(getApplicationContext())。此时应用可能会崩溃,报出前文提到的错误。

发现问题

我们通过log得知有如下打印:“Failed to resolve attribute at index”,那么可以去TypedArray的源码中搜索这个打印发生的地方,发现还不止一处抛出了这个异常,下面粘贴一处:

/**
     * Version of {@link #getDrawable(int)} that accepts an override density.
     * @hide
     */
    @Nullable
    public Drawable getDrawableForDensity(@StyleableRes int index, int density) {
        if (mRecycled) {
            throw new RuntimeException("Cannot make calls to a recycled instance!");
        }

        final TypedValue value = mValue;
        if (getValueAt(index * STYLE_NUM_ENTRIES, value)) {
            if (value.type == TypedValue.TYPE_ATTRIBUTE) {
                throw new UnsupportedOperationException(
                        "Failed to resolve attribute at index " + index + ": " + value);
            }

            if (density > 0) {
                // If the density is overridden, the value in the TypedArray will not reflect this.
                // Do a separate lookup of the resourceId with the density override.
                mResources.getValueForDensity(value.resourceId, density, value, true);
            }
            return mResources.loadDrawable(value, value.resourceId, density, mTheme);
        }
        return null;
    }

源码无秘密,可以看到在value.type == TypedValue.TYPE_ATTRIBUTE时会抛此异常,也就是自定义属性时出的问题,至于具体的原因读者可看源码细查。那么此处我们就知道了此异常的抛出,是因为自定义属性出了问题,就可以看看自定义属性在哪一步骤出了问题。

追查问题

细查自定义属性的3个步骤,最可能就是步骤3的LayoutInflater使用时出了问题,这一个context可能没有获取到我们自定义主题里面默认的自定义属性值,也就是没有获取到步骤2中的值。
最终查看View层的代码,我们发现在Activity中设置了自定义主题,但无论是在Dialog、Window中,还是GridView中,都会崩溃,崩溃信息告诉我们都是找不到自定义属性。最终定位到问题点:找不到自定义属性

解决问题

既然在Activity中设置了自定义主题不够,那就还需要在Application中设置自定义主题,这样在Dialog、Window和GridView中使用到applicationContext时就可以获取到主题的属性,这是提供的第二种解决方式。当然第三种解决方式也和第二种差不多,就是在Dialog、Window和GridView中使用到LayoutInflater.from(applicationContext)时,提前给Application设置自定义主题。

总结

问题原因:找不到自定义属性。
解决办法:

  1. LayoutInflater.from(context)中的context用activity的context或者当前view的context;
  2. 在Application中设置自定义主题;
  3. 就是在Dialog、Window和GridView中使用到LayoutInflater.from(applicationContext)时,提前给Application设置自定义主题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值