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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 18:01:27