Fragment中使用ViewModel时RecyclerView显示空白问题
解决TrackScreen Fragment中RecyclerView空白及「No adapter attached」报错问题
问题根源
日志报错「E/RecyclerView: No adapter attached; skipping layout」的本质是Fragment初始化阶段RecyclerView未绑定适配器,再加上API数据是异步返回,初始列表为空,最终导致页面空白。
解决方案
1. 提前初始化RecyclerView适配器,绑定空列表
不管API数据是否返回,在Fragment的onViewCreated方法中先给RecyclerView设置适配器,初始传入空列表。这样能避免初始化时的适配器缺失报错,同时让RecyclerView处于正常可更新状态。
示例代码:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // 初始化RecyclerView布局管理器 recyclerView.layoutManager = LinearLayoutManager(requireContext()) // 绑定适配器,初始传空列表 val trackAdapter = TrackAdapter(emptyList()) recyclerView.adapter = trackAdapter // 后续观察ViewModel的LiveData更新数据 }
2. 观察ViewModel的LiveData,动态更新适配器数据
在Fragment中正确观察TrackHomeViewModel的LiveData,当API异步返回数据时,更新适配器的数据源并通知RecyclerView刷新。注意使用viewLifecycleOwner作为生命周期所有者,避免内存泄漏。
示例代码:
// 获取共享的TrackHomeViewModel val viewModel = ViewModelProvider(requireActivity())[TrackHomeViewModel::class.java] // 观察LiveData,数据返回时更新适配器 viewModel.getTrackLiveData().observe(viewLifecycleOwner) { trackList -> // 强转适配器并更新数据 (recyclerView.adapter as TrackAdapter).updateData(trackList) }
同时在适配器中添加数据更新方法:
class TrackAdapter(private var trackList: List<Track>) : RecyclerView.Adapter<TrackViewHolder>() { // ... 其他ViewHolder、onBindViewHolder等实现 // 更新数据源并通知刷新 fun updateData(newTrackList: List<Track>) { trackList = newTrackList // 推荐用DiffUtil做局部更新优化,这里先用notifyDataSetChanged做基础实现 notifyDataSetChanged() } }
3. 可选:添加空状态提示(提升用户体验)
当初始列表为空或API返回空数据时,给用户显示友好的空状态提示,避免页面完全空白。可以通过适配器判断列表长度,返回不同的布局:
示例代码:
override fun getItemCount(): Int { // 空列表时返回1个空状态item return if (trackList.isEmpty()) 1 else trackList.size } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { return if (trackList.isEmpty()) { // 加载空状态布局 val emptyView = LayoutInflater.from(parent.context).inflate(R.layout.layout_empty_state, parent, false) EmptyStateViewHolder(emptyView) } else { // 加载正常列表项布局 val itemView = LayoutInflater.from(parent.context).inflate(R.layout.item_track, parent, false) TrackItemViewHolder(itemView) } } // 空状态ViewHolder class EmptyStateViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { // 可初始化空状态的提示文本、按钮等 }
核心思路
先给RecyclerView绑定适配器(哪怕是空数据),解决初始化阶段的「No adapter attached」报错;再通过LiveData监听异步API数据,数据返回后动态更新适配器,让RecyclerView自动刷新展示内容。
内容的提问来源于stack exchange,提问作者Joji
相关产品推荐
相关产品推荐

