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

如何用SavedInstanceState恢复购物车RecyclerView数据及Kotlin实现ChangeNumberItemListener

问题解决:SavedInstanceState恢复数据丢失 + Kotlin实现条目数量变化监听

一、修复SavedInstanceState恢复数据丢失问题

1. 确保数据类正确实现Parcelable

Kotlin推荐使用@Parcelize注解简化实现,避免手动编写序列化代码出错:

import android.os.Parcelable
import kotlinx.parcelize.Parcelize

@Parcelize
data class CartItem(
    val goodsId: String,
    val goodsName: String,
    var count: Int,
    val price: Float
) : Parcelable

注意:需在模块级build.gradle中启用Parcelize插件:

plugins {
    id 'kotlin-parcelize'
}

2. 正确保存数据到Bundle

在Activity的onSaveInstanceState中,确保键名唯一且覆盖所有需要保存的数据:

override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
    // 保存购物车列表
    outState.putParcelableArrayList("cart_list", cartItems)
    // 保存标题文本
    outState.putString("cart_title", tv_cart_title.text.toString())
}

3. 正确恢复数据并更新UI

在onCreate或onRestoreInstanceState中恢复数据,恢复后必须通知Adapter更新:

private lateinit var cartItems: ArrayList<CartItem>
private lateinit var cartAdapter: CartAdapter

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_cart)

    // 初始化数据:优先从保存的状态恢复,否则从Intent获取
    cartItems = if (savedInstanceState != null) {
        savedInstanceState.getParcelableArrayList("cart_list") ?: arrayListOf()
    } else {
        intent.getParcelableArrayListExtra("cart_list") ?: arrayListOf()
    }

    // 恢复标题
    savedInstanceState?.getString("cart_title")?.let {
        tv_cart_title.text = it
    }

    // 初始化Adapter并设置数据
    cartAdapter = CartAdapter(cartItems)
    rv_cart.adapter = cartAdapter
}

常见错误排查

  • 保存与恢复的键名不一致(比如存的是cart_data,取的是cart_list)
  • 数据类Parcelable实现不完整(比如遗漏字段序列化)
  • 恢复数据后未调用adapter.notifyDataSetChanged()或submitList()更新UI

二、Kotlin实现条目数量变化监听(替代直接保存ArrayList思路)

核心是通过监听条目数量变化,实时同步数据源,确保数据源始终与UI状态一致,这样保存时直接存最新数据源即可。

1. 定义数量变化监听接口

interface OnItemCountChangeListener {
    fun onCountChanged(position: Int, newCount: Int)
}

2. 在Adapter中集成监听

class CartAdapter(
    private var cartItems: MutableList<CartItem>,
    private val listener: OnItemCountChangeListener
) : RecyclerView.Adapter<CartAdapter.ViewHolder>() {

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        private val tvCount = itemView.findViewById<TextView>(R.id.tv_count)
        private val btnAdd = itemView.findViewById<Button>(R.id.btn_add)
        private val btnMinus = itemView.findViewById<Button>(R.id.btn_minus)

        fun bind(item: CartItem) {
            tvCount.text = item.count.toString()

            btnAdd.setOnClickListener {
                val newCount = item.count + 1
                // 如果是不可变数据类,用copy创建新对象替换原条目
                // val updatedItem = item.copy(count = newCount)
                // cartItems[adapterPosition] = updatedItem
                item.count = newCount // 可变数据类直接修改
                tvCount.text = newCount.toString()
                listener.onCountChanged(adapterPosition, newCount)
            }

            btnMinus.setOnClickListener {
                if (item.count > 1) {
                    val newCount = item.count - 1
                    item.count = newCount
                    tvCount.text = newCount.toString()
                    listener.onCountChanged(adapterPosition, newCount)
                }
            }
        }
    }

    // 重写onCreateViewHolder、getItemCount等方法...
}

3. 在Activity中实现监听并同步数据源

class CartActivity : AppCompatActivity(), OnItemCountChangeListener {
    private lateinit var cartItems: ArrayList<CartItem>
    private lateinit var cartAdapter: CartAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_cart)

        // 初始化数据逻辑同之前...
        cartAdapter = CartAdapter(cartItems, this)
        rv_cart.adapter = cartAdapter
    }

    override fun onCountChanged(position: Int, newCount: Int) {
        // 实时更新数据源,确保保存时数据是最新的
        cartItems[position].count = newCount
        // 不可变数据类替换写法:
        // cartItems[position] = cartItems[position].copy(count = newCount)
    }

    // onSaveInstanceState保存逻辑同之前...
}

这种方式的优势是:UI操作实时同步数据源,无需额外处理列表状态,在onSaveInstanceState保存时直接用最新的数据源即可,避免状态不一致问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 20:22:54