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

Android RecyclerView未调用Adapter任何函数问题求助(Kotlin)

RecyclerView无内容显示且Adapter方法未被调用的问题

我开发了一个简易Android应用,其中的RecyclerView应展示歌曲列表,但当前无内容显示,且Adapter的所有函数(包括getItemCount)均未被调用。

已尝试的排查操作:

  • 设置RecyclerView背景色,确认其已在屏幕上显示
  • 配置LinearLayoutManager,分别尝试在XML布局和代码中设置,均未解决问题
  • 确认已正确设置Adapter,且Adapter的构造函数已被调用
  • 调试验证数据源列表不为空,getItemCount返回值非0
  • 设置Adapter后调用notifyDataSetChanged(),仍无效果

我并非Android开发新手,曾使用Xamarin、Xamarin Maui进行开发,现在转用Android Studio,但无法定位代码问题,恳请帮助,谢谢。


相关代码

SongAdapter

/**
 * Song adapter
 *
 * @property songs a given list of songs
 * @constructor Create empty Song adapter
 */
class SongAdapter(private val songs: MutableList<Song> = mutableListOf()) : RecyclerView.Adapter<SongAdapter.SongVH>() {

    /**
     * Song view holder
     *
     * @property songDisplayView the song display view being held
     * @constructor Create empty Song view holder
     */
    class SongVH(val songDisplayView: SongDisplayView) : ViewHolder(songDisplayView){
    }

    override fun getItemCount(): Int {
        return songs.count()
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SongVH {
        return SongVH(SongDisplayView(parent.context,null,songs[viewType]))
    }

    override fun onBindViewHolder(holder: SongVH, position: Int) {
        holder.songDisplayView.setSong(songs[position])
    }


    /**
     * Update songs to the given new songs
     *
     * @param newSongs given new songs
     */
    fun updateSongs(newSongs: Iterable<Song>){
        songs.clear()
        songs.addAll(newSongs)
        notifyItemRangeChanged(0,songs.size)
    }

    /**
     * Adds a new song to the song list
     *
     * @param newSong a given new song
     */
    fun addSong(newSong : Song){
        songs.add(newSong)
        notifyItemInserted(songs.size-1)
    }

    /**
     * Removes a song from the song list
     *
     * @param index a given index to remove from
     */
    fun removeSong(index: Int){
        songs.removeAt(index)
        notifyItemRemoved(index)
    }

    /**
     * Updates the song at the given index to a new song
     *
     * @param song the new song
     * @param index a given index
     */
    fun updateSong(song: Song, index: Int){
        songs[index] = song
        notifyItemChanged(index)
    }
}

SongDisplayView

class SongDisplayView(context: Context,attributeSet: AttributeSet?,song: Song = Song()) : LinearLayout(context,attributeSet) {

    private val titleView: TextView = TextView(context)
    init {
        titleView.text = song.name
        titleView.textSize = 18f
        addView(titleView)
    }

    fun setSong(song: Song ) {
        titleView.text = song.name
    }
}

MainActivity

class MainActivity : AppCompatActivity() {

    private lateinit var binding : ActivityMainBinding

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

        binding = ActivityMainBinding.inflate(layoutInflater)

        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }
        val songAdapter = SongAdapter(mutableListOf(Song("Song 1"),Song("Song 2"), Song("Song 3")))
        binding.songsRecycler.adapter = songAdapter
        songAdapter.notifyDataSetChanged()
    }
}

activity_main布局

<?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:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="center"
    android:orientation="vertical"
    tools:context=".MainActivity" >
<TextView
    android:text="hello world"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>
    <androidx.recyclerview.widget.RecyclerView
        android:background="#fadada"
        android:id="@+id/songsRecycler"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

问题诊断与修复

1. 核心问题:ViewBinding使用错误

你在onCreate中先调用setContentView(R.layout.activity_main)加载布局,随后又调用ActivityMainBinding.inflate(layoutInflater)创建了一个全新的视图实例。后续给binding.songsRecycler设置Adapter时,操作的是这个未挂载到界面的RecyclerView,而非屏幕上显示的那个,因此Adapter的所有方法都不会被触发。

修复代码:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    enableEdgeToEdge()
    // 移除原setContentView调用
    binding = ActivityMainBinding.inflate(layoutInflater)
    setContentView(binding.root) // 使用binding的根视图作为界面内容

    ViewCompat.setOnApplyWindowInsetsListener(binding.main) { v, insets ->
        val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
        v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
        insets
    }
    val songAdapter = SongAdapter(mutableListOf(Song("Song 1"),Song("Song 2"), Song("Song 3")))
    binding.songsRecycler.adapter = songAdapter
    // 初始化时已传入数据,无需调用notifyDataSetChanged
}

2. 潜在问题:onCreateViewHolder逻辑错误

你在onCreateViewHolder中用viewType作为索引获取songs[viewType],这是完全错误的——viewType是视图类型标识,并非数据位置。默认情况下所有item的viewType为0,若列表为空会直接引发索引越界异常,即便有数据也不符合ViewHolder的复用设计。

修复代码:

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SongVH {
    // 创建View时不传入song数据,统一在onBindViewHolder中设置
    return SongVH(SongDisplayView(parent.context,null))
}

3. 优化建议:自定义View布局参数完善

SongDisplayView中未给TextView设置布局参数,可能导致显示异常,建议补充:

class SongDisplayView(context: Context, attributeSet: AttributeSet?) : LinearLayout(context,attributeSet) {

    private val titleView: TextView = TextView(context)
    init {
        orientation = VERTICAL
        val textParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)
        textParams.setMargins(16, 16, 16, 16) // 添加边距优化显示
        titleView.textSize = 18f
        titleView.layoutParams = textParams
        addView(titleView)
    }

    fun setSong(song: Song ) {
        titleView.text = song.name
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 21:05:09