记录我的应用程序,我的 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));
}
我搜索了此日志,但没有找到任何有用的内容。怎么知道是什么问题?程序稳定,没有空指针..
提前致谢
问题在于系统无法找到关联的主题来解析这些属性值。 这就是为什么 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。
我也遇到这个问题了。我尝试从源代码中找出解决方案。
日志打印于,
// 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
值。