android.view.InflateException при использовании selectableItemBackground

При раздувании моего макета я получаю это исключение:

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)

В журнале нет «Причинено», но я добавил код для перехвата исключения и вызова 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. И тема необходима AFAICT - рассматриваемый атрибут является частью AppCompat, поэтому для его разрешения требуется тема действия.

Это похоже на вопиющую ошибку, поэтому я не уверен, что я на правильном пути. Любые идеи?


person EboMike    schedule 29.10.2015    source источник
comment
Какую родительскую тему вы использовали для AppTheme?   -  person Fabin Paul    schedule 29.10.2015
comment
@FabinPaul Извините, я должен был упомянуть об этом. Родительская тема — Theme.AppCompat.Light.NoActionBar.   -  person EboMike    schedule 29.10.2015
comment
Вы пытались использовать родительскую тему Base.V7.Theme.AppCompat.Light?   -  person Fabin Paul    schedule 29.10.2015
comment
Пробовал это (конечно, настраивая windowActionBar и windowNoTitle), но это имеет то же исключение при раздувании с той же трассировкой стека.   -  person EboMike    schedule 29.10.2015
comment
Я предполагаю, что это связано с обновлением библиотеки поддержки до 23.0.1 и целевым SDK до 23, но я еще не переключился обратно на 22, чтобы убедиться в этом. Вы правы, у меня была та же проблема, и мне нужно было снова перейти на версию 22. (stackoverflow.com/questions/37376766/)   -  person Luis    schedule 23.05.2016


Ответы (4)


Как говорит @Artjom, проблема заключается в передаче application context при создании пользовательского представления. Я также столкнулся с той же проблемой, и я передавал getApplicationContext() вместо activity как context. После прохождения Activity как context проблема решилась.

Надеюсь, это может помочь кому-то еще.

person Smeet    schedule 15.09.2016

Официальный ответ - вы не можете использовать атрибуты темы для атрибутов android:drawable или android:src. Просто невозможно, по замыслу. Есть еще один ответ, который исследует ту же проблему и предлагает решение: >Как ссылаться на атрибуты стиля из drawable?

В моем случае я не мог этого сделать, так как ?selectableItemBackground AppCompat ссылается на частный рисунок. Поэтому я выбрал кодовое решение - я устанавливаю передний план на ?selectableItemBackground, пока карта не выбрана, и в свой собственный список состояний, который можно нарисовать, когда я нахожусь в режиме выбора.

Это очень уродливое решение, настолько уродливое, что я не буду приводить здесь код, но пока это лучшее, что я смог придумать. Если у кого-то есть лучшее решение, я бы хотел его услышать.

person EboMike    schedule 05.11.2015
comment
Вы уверены, что использовали Activity в качестве Context для надувания, а не ApplicationContext? - person artkoenig; 14.03.2016
comment
Спасибо! Неправильный контекст тоже может быть причиной неудачи - person andre719mv; 26.07.2016
comment
@ArtjomKönig Вы спасли мой день. - person wonsuc; 25.10.2017

К сожалению, другие ответы не мой случай. Способ работы для меня - проверить, использует ли ваша деятельность стиль темы 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>
person Nguyen Tan Dat    schedule 18.06.2018

У меня была такая же ошибка при использовании компонента Androidx Fragment Testing. По умолчанию launchFragmentInContainer() использует тему FragmentScenarioEmptyFragmentActivityTheme, что приводит к ошибке.

Простое решение — использовать собственную тему, расширяющую AppCompat:

launchFragmentInContainer(theme = R.style.AppTheme)

person nmw    schedule 10.06.2019
comment
Это именно тот контекст, который я искал, и он отлично сработал! Спасибо! - person Cassio Landim; 04.08.2020