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

Kotlin中notifyDataSetChanged未生效,列表请求成功但视图无更新如何解决

问题根因
  • 核心错误是你创建了两个ItemsAdapter实例:
    1. 先实例化了itemsAdapter成员变量,和全局的itemsList绑定
    2. 给RecyclerView设置adapter时,又重新new了一个新的ItemsAdapter实例,虽然也绑定了同一个itemsList,但你后续调用notifyDataSetChanged()的是第一个没绑定到RecyclerView的itemsAdapter,所以视图收不到更新通知
  • 次要问题:你创建了分割线实例但没有添加到RecyclerView中,请求数据前也没有清空旧列表,可能会出现数据重复的情况
修复代码
class ItemsFragmentCp : Fragment(), ItemCellClickListener {
    private val itemsList = ArrayList<ItemModel>()
    private lateinit var itemsAdapter: ItemsAdapter

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_items, container, false)
    }

    override fun onViewCreated(itemView: View, savedInstanceState: Bundle?) {
        super.onViewCreated(itemView, savedInstanceState)
        itemsAdapter = ItemsAdapter(itemsList, this)
        val layoutManager = LinearLayoutManager(itemView.context)

        val recyclerView = itemView.findViewById<RecyclerView>(R.id.recyclerView)
        recyclerView.setHasFixedSize(true)
        recyclerView.layoutManager = layoutManager // 复用已创建的layoutManager,无需重复实例化
        recyclerView.adapter = itemsAdapter // 直接使用已初始化的成员变量,不要新建Adapter
        recyclerView.itemAnimator = DefaultItemAnimator()
        // 把创建的分割线添加到RecyclerView中
        val dividerItemDecoration = DividerItemDecoration(
            recyclerView.context,
            layoutManager.orientation
        )
        recyclerView.addItemDecoration(dividerItemDecoration)
        
        val activity = requireActivity()
        val intent = activity.intent
        val settingsJson = intent.getStringExtra("settingsJson").orEmpty()
        val settingsData = SettingsLoaderMyCompany(settingsJson)

        // 加载新数据前清空旧列表,避免重复累加
        itemsList.clear()
        settingsData.getSettings().getEmails().forEach {
            val har = MyCompanyApiRepo()
            val sign = har.makeSign()
            prepareListData(it.getEmail(), sign)
        }

    }

    private fun prepareListData(email :String, sign :String) {
        val request = ServiceBuilder.buildService(MyCompanyApiEndpoints::class.java)
        val call = request.getItems(email, sign)

        call.enqueue(object : Callback<MyCompanyGetItemsList> {
            @SuppressLint("NotifyDataSetChanged")
            override fun onResponse(call: Call<MyCompanyGetItemsList>, response: Response<MyCompanyGetItemsList>) {
                if (response.isSuccessful){
                    val serverResponse : MyCompanyGetItemsList = response.body()!!
                    serverResponse.items.forEach {
                        val item = ItemModel(it.id, it.name, it.datetime)
                        itemsList.add(item)
                    }
                    // 此时notify的是已绑定到RecyclerView的adapter,可正常触发视图更新
                    itemsAdapter.notifyDataSetChanged()
                } else {
                    Log.d("Error", response.toString())
                }
            }
            override fun onFailure(call: Call<MyCompanyGetItemsList>, t: Throwable) {
                //Toast.makeText(context, "${t.message}", Toast.LENGTH_SHORT).show()
            }
        })
    }
}
额外优化建议
  • 性能优化可以用notifyItemRangeInserted代替notifyDataSetChanged,避免全量刷新,还能自带列表插入动画
  • 尽量用requireContext()、requireActivity()代替可空的context、getActivity(),减少空指针风险

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 15:27:03