使用selectableItemBackground时出现android.view.InflateException异常

20

当我扩展我的布局时,会出现以下异常:

E AndroidRuntime: android.view.InflateException: Binary XML file line #11: Binary XML file line #11: Error inflating class <unknown>
E AndroidRuntime:        at android.view.LayoutInflater.inflate(LayoutInflater.java:539)
E AndroidRuntime:        at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
E AndroidRuntime:        at com.myapp.view.MyRecyclerAdapter.onCreateViewHolder(MyRecyclerAdapter:80)
E AndroidRuntime:        at android.support.v7.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:5288)
E AndroidRuntime:        at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4551)
E AndroidRuntime:        at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4461)
E AndroidRuntime:        at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1962)

日志中没有“Caused by”,但我添加了代码来捕获异常并调用getCause(),直到它返回null,以下是事件的顺序:

android.view.InflateException: Binary XML file line #11: Binary XML file line #11: Error inflating class <unknown>
android.view.InflateException: Binary XML file line #11: Error inflating class <unknown>
Error: Binary XML file line #11: Error inflating class <unknown>
android.content.res.Resources$NotFoundException: File res/drawable-v11/selectable_list_background.xml from drawable resource ID #0x7f020096
java.lang.UnsupportedOperationException: Failed to resolve attribute at index 0: TypedValue{t=0x2/d=0x7f0100f9 a=-1}

0x7f020096是selectable_list_background(见下文),它所引用的TypedValue是?selectableItemBackground

我将异常问题缩小到了我的使用?selectableItemBackground上。更具体地说,我正在使用一个CardView:

<android.support.v7.widget.CardView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:foreground="@drawable/selectable_list_background"
    card_view:cardCornerRadius="4dp"
    card_view:cardElevation="4dp"
    >

这是 drawable/selectable_list_background 的相关部分:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="?selectableItemBackground" />
</selector>

这个活动正在使用我自己的主题,其父级是Theme.AppCompat.Light.NoActionBar

这段代码以前可以工作,但是几个月后我找出了这段代码,现在它会因为异常而崩溃。我的猜测是这与将支持库升级到23.0.1和目标SDK升级到23有关,但我还没有切换回22来验证。

如果我删除引用?selectableItemBackground的那一行,一切都正常。我也尝试过?attr/selectableItemBackground?android:attr/selectableItemBackground,但得到了相同的结果。(后者让我相信这可能不是支持库的问题)。

编辑:

我在调试器中看了一下,我怀疑是android.content.res.Resources中的这段代码,在loadDrawable()内部:

Drawable loadDrawable(TypedValue value, int id, Theme theme) throws NotFoundException {
    [...]
    dr = loadDrawableForCookie(value, id, null);

请注意,该函数需要一个主题,但在调用loadDrawableForCookie()时没有传递它,这是最终触发第一个异常的方法。
java.lang.UnsupportedOperationException: Failed to resolve attribute at index 0: TypedValue{t=0x2/d=0x7f0100f9 a=-1}
    at android.content.res.TypedArray.getDrawable(TypedArray.java:867)
    at android.graphics.drawable.StateListDrawable.inflateChildElements(StateListDrawable.java:170)
    at android.graphics.drawable.StateListDrawable.inflate(StateListDrawable.java:115)
    at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:1215)
    at android.graphics.drawable.Drawable.createFromXml(Drawable.java:1124)
    at android.content.res.Resources.loadDrawableForCookie(Resources.java:2630)
    at android.content.res.Resources.loadDrawable(Resources.java:2540)
    at android.content.res.TypedArray.getDrawable(TypedArray.java:870)
    at android.view.View.<init>(View.java:4280)

这个代码似乎是Android 6.0版本中新增的 - 5.0版本中的代码有很大不同,但在加载drawable时传递了主题。而且据我所知,主题是必需的 - 相关的属性属于AppCompat,因此需要活动主题来解决它。

不过这似乎是一个明显的错误,所以我并不确定我走对了路。有什么想法吗?


你在AppTheme中使用的父主题是哪一个? - Fabin Paul
@FabinPaul 抱歉,我之前应该提到。父主题是 Theme.AppCompat.Light.NoActionBar - EboMike
你试过使用父主题Base.V7.Theme.AppCompat.Light吗? - Fabin Paul
尝试过了(当然调整了windowActionBarwindowNoTitle),但是在膨胀时仍然出现相同的异常,具有相同的堆栈跟踪。 - EboMike
我的猜测是这与将支持库升级到23.0.1和目标 SDK 设为 23 有关,但我还没有切换回 22 来验证。你是对的,我也遇到了同样的问题,需要切换回版本 22。(http://stackoverflow.com/questions/37376766/unable-to-start-activity-componentinfo-android-view-inflateexception-binary-xml/37380072#37380072) - Luis
4个回答

7

正如@Artjom所说,问题出在创建自定义视图时传递应用程序上下文。我之前也面临同样的问题,我传递了getApplicationContext()而不是activity作为context。将Activity作为context传递后,问题得到了解决。

希望对其他人有所帮助。


6
官方答案是 - 按设计,您不能使用主题属性来设置android:drawableandroid:src属性。这是不可能的。还有另一个答案探讨了同样的问题并提供了解决方案:如何从可绘制项引用样式属性? 在我的情况下,我无法这样做,因为AppCompat的?selectableItemBackground引用了一个私有的可绘制项。所以我选择了一种代码解决方案 - 当卡片未被选中时,将前景设置为?selectableItemBackground,一旦进入选择模式,就将其设置为我的自定义状态列表可绘制项。
这是一个非常丑陋的解决方案,太丑陋了,我不会在这里分享代码,但这是我目前能想到的最好的解决方案。如果有更好的解决方案,我很乐意听取建议。

8
你确定你使用了Activity作为上下文来填充布局而不是ApplicationContext吗? - artkoenig
谢谢!错误的上下文也可能是失败的原因。 - andre719mv
{btsdaf} - wonsuc

2
当我使用androidx Fragment Testing组件时,遇到了相同的错误。默认情况下,launchFragmentInContainer()使用主题FragmentScenarioEmptyFragmentActivityTheme,导致出现错误。
简单的解决方法是使用扩展了AppCompat的自定义主题: launchFragmentInContainer(theme = R.style.AppTheme) "Original Answer"翻译成"最初的回答"

这正是我所需要的上下文,并且完美地运作了!谢谢! - Cassio Landim

1
很遗憾,其他答案并不适用于我的情况。对我而言,解决方法是检查您的活动是否使用了AppCompat主题样式:
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
    </style>

然后在你的活动中使用AppCompat主题(有很多种方法,但我展示一种使用清单的方式):

<application
        android:name=".Abbott"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

    <!-- Any configuration inside -->

</application>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接