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

Android订餐APP开发:如何将ListView选中项从Adapter存入ArrayList并传递至Activity

解决订餐APP中ListView选中项数据传递到Activity的问题

看起来你在开发订餐APP时遇到了ListView选中项数据存储和传递的问题,我来帮你梳理下解决方案,先说说你现有代码的几个核心问题,再给你完整的改进方案:

你当前代码的问题

  1. 数据存储位置错误:你把arridProduct、arrTotalPrice、arrQuantity定义在getView方法里,每次ListView刷新或者滚动调用getView时,这些数组都会被重新创建,之前选中的数据直接丢失,根本存不住。
  2. 未处理ListView复用:ListView的convertView是复用机制,你没有在getView里恢复控件的选中状态和数量值,滚动后会出现控件状态混乱的问题。
  3. 缺少与Activity的交互机制:你在Adapter里操作数据,但没有办法把这些数据传递到Activity中。

完整解决方案

步骤1:创建封装选中项的数据类

首先我们创建一个CartItem类,把商品的id、数量、价格封装在一起,方便后续传递:

// 实现Parcelable接口,方便通过Intent传递到其他Activity
@Parcelize
data class CartItem(
    val id: String,
    var quantity: Int,
    val price: String
) : Parcelable

步骤2:重构你的Adapter

我们把选中状态的存储移到Adapter的成员变量中,添加回调接口让Activity能实时获取数据变化,同时处理ListView复用的问题:

// 定义回调接口,让Adapter通知Activity选中项的变化
interface OnCartItemChangeListener {
    fun onCartItemAdded(item: CartItem)
    fun onCartItemRemoved(itemId: String)
    fun onQuantityChanged(itemId: String, newQuantity: Int)
}

class ProductAdapter(
    private val myContext: Context,
    private val productList: List<Product>, // 这里假设你有Product数据类存储商品信息
    private val cartChangeListener: OnCartItemChangeListener
) : BaseAdapter() {

    // 用MutableMap记录选中的商品,key是商品id,value是选中的数量
    private val selectedItems = mutableMapOf<String, Int>()

    override fun getCount(): Int = productList.size

    override fun getItem(position: Int): Product = productList[position]

    override fun getItemId(position: Int): Long = position.toLong()

    override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
        // 复用convertView,提升性能
        val view = convertView ?: LayoutInflater.from(myContext)
            .inflate(R.layout.list_product, parent, false)

        val currentProduct = productList[position]
        val productId = currentProduct.idProduct

        // 初始化控件
        val textNamaProduct = view.findViewById<TextView>(R.id.textViewNamaProduct)
        val textHargaProduct = view.findViewById<TextView>(R.id.textViewHargaProduct)
        val checkBoxAddProduct = view.findViewById<CheckBox>(R.id.checkBoxAddProduct)
        val numPickerQuantity = view.findViewById<NumberPicker>(R.id.numberPickerQuantity)
        val buttonAddToCart = view.findViewById<Button>(R.id.buttonAddToCart)

        // 设置商品基础信息
        textNamaProduct.text = currentProduct.nama.toString()
        textHargaProduct.text = currentProduct.price.toString()

        // 恢复控件状态(解决ListView复用的问题)
        val isSelected = selectedItems.containsKey(productId)
        checkBoxAddProduct.isChecked = isSelected
        // 根据选中状态设置NumberPicker的范围
        if (isSelected) {
            numPickerQuantity.maxValue = 10
            numPickerQuantity.minValue = 1
            numPickerQuantity.value = selectedItems[productId] ?: 1
        } else {
            numPickerQuantity.maxValue = 0
            numPickerQuantity.minValue = 0
        }

        // CheckBox点击事件处理
        checkBoxAddProduct.setOnClickListener {
            if (checkBoxAddProduct.isChecked) {
                // 选中商品,记录数量
                val quantity = numPickerQuantity.value
                selectedItems[productId] = quantity
                // 通知Activity添加了购物项
                cartChangeListener.onCartItemAdded(
                    CartItem(productId, quantity, currentProduct.price.toString())
                )
                // 启用NumberPicker
                numPickerQuantity.maxValue = 10
                numPickerQuantity.minValue = 1
            } else {
                // 取消选中,移除记录
                selectedItems.remove(productId)
                // 通知Activity移除了购物项
                cartChangeListener.onCartItemRemoved(productId)
                // 禁用NumberPicker
                numPickerQuantity.maxValue = 0
                numPickerQuantity.minValue = 0
            }
        }

        // 监听数量变化
        numPickerQuantity.setOnValueChangedListener { _, _, newVal ->
            if (checkBoxAddProduct.isChecked) {
                selectedItems[productId] = newVal
                // 通知Activity数量更新了
                cartChangeListener.onQuantityChanged(productId, newVal)
            }
        }

        // 加入购物车按钮点击事件(如果需要通过按钮触发,而不是CheckBox自动处理)
        buttonAddToCart.setOnClickListener {
            if (checkBoxAddProduct.isChecked) {
                val quantity = numPickerQuantity.value
                cartChangeListener.onCartItemAdded(
                    CartItem(productId, quantity, currentProduct.price.toString())
                )
            }
        }

        return view
    }

    // 提供方法让Activity主动获取所有选中的购物项
    fun getSelectedCartItems(): List<CartItem> {
        return selectedItems.map { entry ->
            val product = productList.find { it.idProduct == entry.key }!!
            CartItem(entry.key, entry.value, product.price.toString())
        }
    }
}

步骤3:在Activity中使用Adapter并接收数据

在你的Activity里实现回调接口,或者直接调用Adapter的方法获取选中数据,然后传递到目标Activity:

class OrderActivity : AppCompatActivity(), ProductAdapter.OnCartItemChangeListener {

    private lateinit var productAdapter: ProductAdapter
    // 也可以在Activity里维护购物车数据,实时更新
    private val cartItems = mutableListOf<CartItem>()

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

        // 从数据库获取商品列表(替换成你实际的数据库查询逻辑)
        val productList = fetchProductsFromDatabase()

        // 初始化Adapter,传入回调
        productAdapter = ProductAdapter(this, productList, this)
        val listView = findViewById<ListView>(R.id.listViewProducts)
        listView.adapter = productAdapter

        // 比如点击"去购物车"按钮时,获取选中项并传递
        findViewById<Button>(R.id.btn_go_to_cart).setOnClickListener {
            val selectedItems = productAdapter.getSelectedCartItems()
            // 通过Intent传递数据到购物车Activity
            val intent = Intent(this, CartActivity::class.java)
            intent.putParcelableArrayListExtra("cart_items", ArrayList(selectedItems))
            startActivity(intent)
        }
    }

    // 实现回调方法,实时处理选中项变化
    override fun onCartItemAdded(item: CartItem) {
        // 移除已存在的同id项,避免重复
        cartItems.removeAll { it.id == item.id }
        cartItems.add(item)
        // 这里可以更新UI,比如显示购物车数量
    }

    override fun onCartItemRemoved(itemId: String) {
        cartItems.removeAll { it.id == itemId }
        // 更新UI
    }

    override fun onQuantityChanged(itemId: String, newQuantity: Int) {
        cartItems.find { it.id == itemId }?.let {
            it.quantity = newQuantity
        }
        // 更新UI
    }

    // 模拟从数据库获取商品的方法
    private fun fetchProductsFromDatabase(): List<Product> {
        // 替换成你实际的数据库查询逻辑
        return emptyList()
    }
}

步骤4:在目标Activity接收数据

在购物车Activity里获取传递过来的CartItem列表:

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

        val cartItems = intent.getParcelableArrayListExtra<CartItem>("cart_items") ?: emptyList()
        // 这里可以用cartItems来展示购物车内容
    }
}

关键要点总结

  • 避免在getView里存储数据:所有需要持久化的选中状态数据,要放在Adapter的成员变量中,防止每次getView调用丢失数据。
  • 处理ListView复用:在getView里一定要恢复控件的状态,不然滚动后会出现状态混乱的问题。
  • 通过回调或方法传递数据:Adapter和Activity之间通过回调接口实时交互,或者提供方法让Activity主动获取数据,再通过Intent传递到其他页面。

内容的提问来源于stack exchange,提问作者LEVIN VITO _

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 21:42:43