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

Kotlin开发TabbedActivity时RecyclerView报No adapter attached错误

错误原因

  • 核心问题:RecyclerView的layoutManager和adapter是在Retrofit的异步网络请求回调里才设置的,界面首次渲染阶段RecyclerView没有绑定任何适配器,所以触发了No adapter attached; skipping layout警告
  • 额外问题1:类名命名为thirdtabFragment但实际继承了AppCompatActivity,如果是Tab页对应的组件应该继承Fragment,逻辑也需要对应调整(如果实际是独立Activity可忽略该点)
  • 额外问题2:使用response.body()!!非空断言风险极高,网络请求返回的body可能为空,会直接触发崩溃

修复方案

首先改造ScoreAdapter支持动态更新数据:

class ScoreAdapter(private var contenderList: List<Item> = emptyList()) : RecyclerView.Adapter<ScoreAdapter.ViewHolder>() {

    // 新增数据更新方法
    fun updateData(newList: List<Item>) {
        contenderList = newList
        notifyDataSetChanged()
        // 后续可替换为DiffUtil提升列表刷新性能
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.score_row, parent, false)
        return ViewHolder(view)
    }

    override fun getItemCount() = contenderList.size

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val contender = contenderList[position]
        holder.contenderName.text = contender.contenderName
    }


    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
        val contenderName: TextView = itemView.findViewById(R.id.contenderName_tv)
    }
}

如果当前类是独立Activity,改造thirdtabFragment逻辑:

class thirdtabFragment : AppCompatActivity() {

    private lateinit var binding: ThirdtabBinding
    // 提前初始化适配器
    private val scoreAdapter = ScoreAdapter()
    override fun onCreate(savedInstanceState: Bundle?){
        super.onCreate(savedInstanceState)

        binding = ThirdtabBinding.inflate(layoutInflater)
        val view = binding.root
        setContentView(view)
        // 页面初始化阶段就完成RecyclerView配置
        binding.recyclerView.apply {
            layoutManager = LinearLayoutManager(this@thirdtabFragment)
            adapter = scoreAdapter
        }
        
        val apiInterface = APIClient.client.create(ApiInterface::class.java)

        val call = apiInterface.getScore()
        call.enqueue(object : Callback<List<Item>> {
            override fun onResponse(call: Call<List<Item>>, response: Response<List<Item>>) {
                Log.d("Success!", response.toString())
                // 替换非空断言做空安全处理
                response.body()?.let { list ->
                    showContenders(list)
                } ?: run {
                    Log.e("Query Error", "返回数据为空")
                }
            }

            override fun onFailure(call: Call<List<Item>>, t: Throwable) {
                Log.e("Failed Query :(", t.toString())
            }
        })
    }

    private fun showContenders(contenderList: List<Item>) {
        // 直接更新适配器数据
        scoreAdapter.updateData(contenderList)
    }
}

如果当前类是Tab页对应的Fragment,调整为Fragment标准逻辑:

class thirdtabFragment : Fragment() {
    private var _binding: ThirdtabBinding? = null
    private val binding get() = _binding!!
    private val scoreAdapter = ScoreAdapter()

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = ThirdtabBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // 初始化RecyclerView
        binding.recyclerView.apply {
            layoutManager = LinearLayoutManager(requireContext())
            adapter = scoreAdapter
        }
        // 发起网络请求
        val apiInterface = APIClient.client.create(ApiInterface::class.java)
        val call = apiInterface.getScore()
        call.enqueue(object : Callback<List<Item>> {
            override fun onResponse(call: Call<List<Item>>, response: Response<List<Item>>) {
                Log.d("Success!", response.toString())
                response.body()?.let { list ->
                    showContenders(list)
                } ?: run {
                    Log.e("Query Error", "返回数据为空")
                }
            }

            override fun onFailure(call: Call<List<Item>>, t: Throwable) {
                Log.e("Failed Query :(", t.toString())
            }
        })
    }

    private fun showContenders(contenderList: List<Item>) {
        scoreAdapter.updateData(contenderList)
    }

    override fun onDestroyView() {
        super.onDestroyView()
        // 清理绑定避免内存泄漏
        _binding = null
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 10:06:01