You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android应用InflateException报错求助:RecyclerView加载海报布局失败

Android RecyclerView布局膨胀崩溃问题解决方案

问题场景

用Kotlin开发讲座推荐APP,通过Retrofit2获取图片URL并在主界面RecyclerView展示海报时,APP崩溃,报错信息如下:

E/RecyclerView: No adapter attached; skipping layout
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.looc, PID: 19848
    android.view.InflateException: Binary XML file line #2 in com.example.looc:layout/item_poster: Binary XML file line #2 in com.example.looc:layout/item_poster: Error inflating class <unknown>
    Caused by: android.view.InflateException: Binary XML file line #2 in com.example.looc:layout/item_poster: Error inflating class <unknown>
    Caused by: java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Constructor.newInstance0(Native Method)
        ...
     Caused by: java.lang.UnsupportedOperationException: Failed to resolve attribute at index 35: TypedValue{t=0x2/d=0x7f03036b a=-1}
        at android.content.res.TypedArray.getDrawableForDensity(TypedArray.java:998)
        ...

相关代码与布局

item_poster.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:foreground="?selectableItemBackgroundBorderless"
    android:layout_margin="2dp"
    android:clickable="true"
    android:focusable="true"
    android:orientation="vertical"
    tools:targetApi="m"
    tools:ignore="UnusedAttribute">

    <ImageView
        android:id="@+id/poster_image"
        android:layout_width="105dp"
        android:layout_height="140dp"
        android:scaleType="centerCrop"
        android:background="@drawable/poster_bg" />

</LinearLayout>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:background="@color/main_background_color"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".view.MainActivity">

    <androidx.fragment.app.FragmentContainerView
        android:layout_width="match_parent"
        android:layout_height="260dp"
        android:layout_marginBottom="10dp"
        android:id="@+id/fragment_first"
        android:name="com.example.looc.view.FeedFragment"/>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recommend_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="10dp"
        android:nestedScrollingEnabled="false"
        android:orientation="horizontal"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        tools:listitem="@layout/item_poster" />

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_nav_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:background="@color/black"
        app:itemIconTint="@color/bottom_navigation_color"
        app:itemTextColor="@color/bottom_navigation_color"
        app:menu="@menu/bottom_navigation_menu" />

</LinearLayout>

MainActivity.kt

package com.example.looc.view

import RetrofitInterface
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.recyclerview.widget.RecyclerView
import com.example.looc.R
import com.example.looc.data.LectureDetailItem
import com.example.looc.server.RetrofitClient
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import java.io.IOException
import java.net.HttpURLConnection
import java.net.URL

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val recommendRecyclerView = findViewById<RecyclerView>(R.id.recommend_recycler_view)
        val recommendLectureList = mutableListOf<String>()

        val retrofit = RetrofitClient.retrofit
        retrofit.create(RetrofitInterface::class.java).getLectures().enqueue(object : Callback<ArrayList<LectureDetailItem>>{
            override fun onResponse(
                call: Call<ArrayList<LectureDetailItem>>,
                response: Response<ArrayList<LectureDetailItem>>
            ) {
                if(response.isSuccessful){
                    val lecturePoster = response.body()
                    recommendLectureList.add("http://172.16.0.94:5000/static/images/"+lecturePoster!!.get(0).image)
                    recommendRecyclerView.adapter = RecyclerViewAdapter(recommendLectureList, LayoutInflater.from(applicationContext))
                }
            }
            override fun onFailure(call: Call<ArrayList<LectureDetailItem>>, t: Throwable) {
                Log.d("testt", "메인화면 이미지 불러오기 실패")
            }
        })
    }
}

class RecyclerViewAdapter(
    var lectureList : List<String>,
    var inflater: LayoutInflater
) : RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder>(){

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
        val lectureImage : ImageView
        val context = itemView.context
        init {
            lectureImage = itemView.findViewById(R.id.poster_image)
            itemView.setOnClickListener {
                val intent = Intent(context, DetailedPageActivity::class.java)
                intent.run { context.startActivity(this) }
            }
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = inflater.inflate(R.layout.item_poster, parent, false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
//        Log.d("testt", lectureList.get(0))
//        holder.lectureImage.setImageBitmap(loadImage(lectureList.get(position)))
    }

    override fun getItemCount(): Int {
        return  1
    }

    fun loadImage(imageUrl: String): Bitmap? {
        var bitmap: Bitmap? = null
        val connection: HttpURLConnection?
        try {
            val url = URL(imageUrl)
            connection = url.openConnection() as HttpURLConnection
            connection.requestMethod = "GET"
            connection.connectTimeout = 10000
            connection.doOutput = true
            connection.doInput = true
            connection.useCaches = true
            connection.connect()
            val resCode = connection.responseCode
            if (resCode == HttpURLConnection.HTTP_OK) {
                val input = connection.inputStream
                bitmap = BitmapFactory.decodeStream(input)
                connection.disconnect()
            }
        } catch (e: IOException) {
            e.printStackTrace()
        }
        return bitmap
    }
}

问题分析与解决步骤

1. 修复布局属性兼容性问题

报错核心是?selectableItemBackgroundBorderless仅在API 21+可用,即使添加tools:targetApi="m",低版本系统运行时仍会尝试解析该属性导致崩溃。

修改方案:
替换为兼容API 11+的属性?attr/selectableItemBackground,修改后的item_poster.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:foreground="?attr/selectableItemBackground"
    android:layout_margin="2dp"
    android:clickable="true"
    android:focusable="true"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/poster_image"
        android:layout_width="105dp"
        android:layout_height="140dp"
        android:scaleType="centerCrop"
        android:background="@drawable/poster_bg" />

</LinearLayout>

2. 提前设置RecyclerView适配器

No adapter attached; skipping layout是因为RecyclerView初始化时未设置适配器,网络请求完成后才赋值,导致布局测量阶段无适配器。

修改方案:
在onCreate中提前设置空适配器,网络请求成功后更新数据并通知适配器:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val recommendRecyclerView = findViewById<RecyclerView>(R.id.recommend_recycler_view)
    val recommendLectureList = mutableListOf<String>()
    // 提前初始化空适配器
    val adapter = RecyclerViewAdapter(recommendLectureList, LayoutInflater.from(this))
    recommendRecyclerView.adapter = adapter

    val retrofit = RetrofitClient.retrofit
    retrofit.create(RetrofitInterface::class.java).getLectures().enqueue(object : Callback<ArrayList<LectureDetailItem>>{
        override fun onResponse(
            call: Call<ArrayList<LectureDetailItem>>,
            response: Response<ArrayList<LectureDetailItem>>
        ) {
            if(response.isSuccessful){
                val lecturePoster = response.body()
                lecturePoster?.let {
                    recommendLectureList.clear()
                    recommendLectureList.add("http://172.16.0.94:5000/static/images/${it[0].image}")
                    // 通知适配器数据更新
                    adapter.notifyDataSetChanged()
                }
            }
        }
        override fun onFailure(call: Call<ArrayList<LectureDetailItem>>, t: Throwable) {
            Log.d("testt", "메인화면 이미지 불러오기 실패")
        }
    })
}

3. 优化RecyclerView适配器

  • 修改getItemCount()返回列表实际长度,避免固定值导致数据展示异常:
override fun getItemCount(): Int {
    return lectureList.size
}
  • 替换手动图片加载逻辑,使用Glide库(需在build.gradle添加依赖)避免主线程网络操作:
// 先添加Glide依赖
// implementation 'com.github.bumptech.glide:glide:4.16.0'
// annotationProcessor 'com.github.bumptech.glide:compiler:4.16.0'

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    Glide.with(holder.context)
        .load(lectureList[position])
        .placeholder(R.drawable.poster_bg) // 设置占位图
        .into(holder.lectureImage)
}

同时删除手动实现的loadImage方法。

4. 基础检查

  • 确保@drawable/poster_bg资源存在;
  • 在AndroidManifest.xml中添加网络权限:<uses-permission android:name="android.permission.INTERNET" />。

内容的提问来源于stack exchange,提问作者kei

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 05:35:29