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
相关产品推荐
相关产品推荐

