Logcat 说:“资源具有未解析的主题属性”

问题描述 投票:0回答:2

记录我的应用程序,我的 Logcat 说:警告:

... has unresolved theme attributes! Consider using Resources.getDrawable(int, Theme) or Context.getDrawable(int).

产生警告的代码:

    if (mCards.get(position).isFavorite()) {
        viewHolder.mIbStar
                .setImageDrawable(mContext.getResources()
                                          .getDrawable(R.drawable.btn_is_fav));
    } else {
        viewHolder.mIbStar
                .setImageDrawable(mContext.getResources()
                                          .getDrawable(R.drawable.btn_isnt_fav));
    }

我搜索了此日志,但没有找到任何有用的内容。怎么知道是什么问题?程序稳定,没有空指针..

提前致谢

android resources warnings drawable logcat
2个回答
11
投票

问题在于系统无法找到关联的主题来解析这些属性值。 这就是为什么 logcat 建议您使用提供主题的 Resources.getDrawable(int, Theme) 方法, 或者使用 Context.getDrawable(int) 方法,其中 Context 将使用其当前主题:

返回与特定资源 ID 关联的可绘制对象 适合当前主题的样式。

此外,根据Android官方文档: http://developer.android.com/reference/android/content/res/Resources.html#getDrawable(int)

此方法在 API 级别 22 中已弃用。请改用 getDrawable(int, Theme)

更具体地说

注意:要获取主题可绘制对象,请使用 Context.getDrawable(int)getDrawable(int, Theme) 传递所需的主题。

考虑更换

mContext.getResources().getDrawable(int) 

mContext.getDrawable(int)

例如建议使用 logcat。


0
投票

我也遇到这个问题了。我尝试从源代码中找出解决方案。

日志打印于,

    // android.content.res.Resources#getDrawable(int)
    public Drawable getDrawable(@DrawableRes int id) throws NotFoundException {
        final Drawable d = getDrawable(id, null);
        if (d != null && d.canApplyTheme()) {
            Log.w(TAG, "Drawable " + getResourceName(id) + " has unresolved theme "
                    + "attributes! Consider using Resources.getDrawable(int, Theme) or "
                    + "Context.getDrawable(int).", new RuntimeException());
        }
        return d;
    }

这是一个警告日志,如果Drawable的

canApplyTheme
方法返回true,那么它将打印该日志。

所以,不同种类的drawable会有不同的该方法的实现。

在我的例子中,我使用了 GradientDrawable(由 xml 可绘制对象定义)。那么,我们来看看GradientDrawable的方法吧。

// android.graphics.drawable.GradientDrawable#canApplyTheme
    @Override
    public boolean canApplyTheme() {
        return (mGradientState != null && mGradientState.canApplyTheme()) || super.canApplyTheme();
    }

GradientDrawable 尝试从

canApplyTheme
mGradientState
方法获取值。
mGradientState
是一个 GradientState。

对于GradientState,其

canApplyTheme
定义如下,

// android.graphics.drawable.GradientDrawable.GradientState#canApplyTheme
        @Override
        public boolean canApplyTheme() {
            boolean mGradientColorState = mGradientColors != null;
            if (mGradientColors != null) {
                for (int i = 0; i < mGradientColors.length; i++) {
                    mGradientColorState |= (mGradientColors[i] != null && mGradientColors[i]
                        .canApplyTheme());
                }
            }
            return mThemeAttrs != null
                    || mAttrSize != null || mAttrGradient != null
                    || mAttrSolid != null || mAttrStroke != null
                    || mAttrCorners != null || mAttrPadding != null
                    || (mTint != null && mTint.canApplyTheme())
                    || (mStrokeColors != null && mStrokeColors.canApplyTheme())
                    || (mSolidColors != null && mSolidColors.canApplyTheme())
                    || mGradientColorState
                    || super.canApplyTheme();
        }

因此,如果

mThemeAttrs
不为 null,则
canApplyTheme
方法将返回 true。

至于

mThemeAttrs
,它源自TypedArray的
extractThemeAttrs
方法。在
extractThemeAttrs
方法中,

// android.content.res.TypedArray#extractThemeAttrs(int[])
    public int[] extractThemeAttrs(@Nullable int[] scrap) {
        if (mRecycled) {
            throw new RuntimeException("Cannot make calls to a recycled instance!");
        }

        int[] attrs = null;

        final int[] data = mData;
        final int N = length();
        for (int i = 0; i < N; i++) {
            final int index = i * STYLE_NUM_ENTRIES;
            if (data[index + STYLE_TYPE] != TypedValue.TYPE_ATTRIBUTE) {
                // Not an attribute, ignore.
                continue;
            }
        // ....
    }

因此,显然,如果您的资源具有 TypedValue.TYPE_ATTRIBUTE 类型属性,则将打印日志。

什么是

TypedValue.TYPE_ATTRIBUTE
,是诸如
?attr:xxxx
之类的属性。因此,解决方案是尝试从 drwable 中删除
?attr
值。

© www.soinside.com 2019 - 2024. All rights reserved.