如何通过Adapter按钮更新PosActivity中的TextView?
问题描述
我希望点击MyAdapter中的按钮(实现数量增减、删除RecyclerView卡片)时,更新PosActivity内的TextView,但一直找不到解决方法。以下是我尝试的代码:
MyAdapter 代码
package com.mycodlabs.pos.ui.sale.adapter import android.content.Context import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import com.mycodlabs.pos.R import com.mycodlabs.pos.domain.inventory.ProductModel import kotlinx.android.synthetic.main.pos_item_card.view.* import java.math.BigDecimal class MyAdapter(mUx: Context, var selectedItems: ArrayList<ProductModel>) : RecyclerView.Adapter<MyAdapter.ViewHolder>() { val mUx = mUx var totalPrice = BigDecimal.ZERO class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { var pclose = itemView.removeItempos var pname = itemView.pos_name var pprice = itemView.pos_price var pqty = itemView.pos_qty var pminus = itemView.cart_minus_img var pplus = itemView.cart_plus_img } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.pos_item_card, parent, false) return ViewHolder(view) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { val pos: ProductModel = selectedItems[position] holder.pname.text = pos.name holder.pprice.text = pos.unitPrice.toString() holder.pqty.text = pos.quantity.toString() holder.pclose.setOnClickListener { selectedItems.removeAt(position) notifyDataSetChanged() notifyItemRangeChanged(position, selectedItems.size) } holder.pminus.setOnClickListener { if(pos.quantity > 1 ){ pos.quantity -= 1 notifyItemChanged(position) } } holder.pplus.setOnClickListener { pos.quantity += 1 notifyItemChanged(position) } } fun grandTotal(items: ArrayList<ProductModel>): BigDecimal { totalPrice = BigDecimal.ZERO for (i in items.indices) { totalPrice += items[i].unitPrice.multiply(items[i].quantity.toBigDecimal()) } return totalPrice } fun clearData() { selectedItems.clear() notifyDataSetChanged() } override fun getItemCount() = selectedItems.size }
PosActivity 代码
package com.mycodlabs.pos.ui import android.os.Bundle import android.view.View import android.widget.* import androidx.appcompat.app.AppCompatActivity import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.google.android.material.bottomsheet.BottomSheetBehavior import com.mycodlabs.pos.R import com.mycodlabs.pos.db.AndroidDatabase import com.mycodlabs.pos.db.DatabaseTables import com.mycodlabs.pos.db.inventory.InventoryDbo import com.mycodlabs.pos.db.sale.SalesLinesDao import com.mycodlabs.pos.domain.inventory.ProductModel import com.mycodlabs.pos.ui.sale.adapter.MyAdapter import kotlinx.android.synthetic.main.activity_pos.* import kotlinx.android.synthetic.main.adapter_available_promotions.* import kotlinx.android.synthetic.main.dialog_paymentsuccession.view.* import kotlinx.android.synthetic.main.dialog_saleedit.* import kotlinx.android.synthetic.main.layout_addcategory.* import kotlinx.android.synthetic.main.layout_sale.* import kotlinx.android.synthetic.main.listview_stock.* import kotlinx.android.synthetic.main.pos_bottom_sheet.* import kotlinx.android.synthetic.main.pos_item_card.* class PosActivity : AppCompatActivity() { private lateinit var bottomSheetBehavior: BottomSheetBehavior<LinearLayout> private lateinit var recyclerView: RecyclerView private lateinit var db: SalesLinesDao var selectedItems = ArrayList<ProductModel>() val adapter = MyAdapter(this,selectedItems) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_pos) back.setOnClickListener { finish() } check_out_Pos.setOnClickListener{ adapter.clearData() } val autoCompleteTextView = findViewById<AutoCompleteTextView>(R.id.searchBoxPos) val productNames = ArrayList<String>() val dbHelper = AndroidDatabase(this) val db = dbHelper.readableDatabase val cursor = db.rawQuery( "SELECT DISTINCT ${InventoryDbo.colm_productName} FROM ${DatabaseTables.TABLE_PRODUCT} WHERE ${InventoryDbo.colm_productName} like '%%'", null ) if (cursor.moveToFirst()) { do { productNames.add(cursor.getString(cursor.getColumnIndex(InventoryDbo.colm_productName))) } while (cursor.moveToNext()) } cursor.close() db.close() val adapterr = ArrayAdapter(this, android.R.layout.simple_dropdown_item_1line, productNames) autoCompleteTextView.setAdapter(adapterr) val recyclerView = findViewById<RecyclerView>(R.id.sale_List_Pos) val layoutManager = LinearLayoutManager(this) recyclerView.layoutManager = layoutManager recyclerView.adapter = adapter searchBoxPos.setOnItemClickListener { _, _, position, _ -> val selectedItem = autoCompleteTextView.adapter.getItem(position).toString() val selectedProduct = InventoryDbo.getInstance(applicationContext).getPosProductByName(selectedItem).first() selectedItems.add(selectedProduct) adapter.notifyDataSetChanged() searchBoxPos.clearFocus() searchBoxPos.setText("") total_items_Pos.text = adapter.grandTotal(selectedItems).toString() } bottomSheetBehavior = BottomSheetBehavior.from<LinearLayout>(std_btm_sht) bottomSheetBehavior.setBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() { override fun onStateChanged(bottomSheet: View, state: Int) { when (state) { BottomSheetBehavior.STATE_EXPANDED, BottomSheetBehavior.STATE_COLLAPSED, BottomSheetBehavior.STATE_DRAGGING, BottomSheetBehavior.STATE_SETTLING, BottomSheetBehavior.STATE_HALF_EXPANDED -> { total_items_Pos.text = adapter.grandTotal(selectedItems).toString() } else -> {} } } override fun onSlide(bottomSheet: View, slideOffset: Float) { } }) } }
解决方案:接口回调实现数据同步
要实现Adapter按钮操作实时更新Activity的TextView,通过接口回调是最直接可靠的方式,让Adapter在数据变化时通知Activity更新UI。
步骤1:在MyAdapter中定义回调接口
在MyAdapter类内部添加接口,用于传递数据变更事件:
interface OnItemChangeListener { fun onDataChanged() // 数量调整、删除卡片时触发 }
修改Adapter构造函数,传入回调实例:
class MyAdapter( mUx: Context, var selectedItems: ArrayList<ProductModel>, private val listener: OnItemChangeListener // 新增回调参数 ) : RecyclerView.Adapter<MyAdapter.ViewHolder>() { // ... 原有代码 ... }
步骤2:按钮点击时触发回调
修改三个按钮的点击逻辑,每次数据变更后调用回调方法:
override fun onBindViewHolder(holder: ViewHolder, position: Int) { val pos: ProductModel = selectedItems[position] // ... 原有赋值代码 ... holder.pclose.setOnClickListener { selectedItems.removeAt(position) notifyDataSetChanged() notifyItemRangeChanged(position, selectedItems.size) listener.onDataChanged() // 通知Activity更新 } holder.pminus.setOnClickListener { if(pos.quantity > 1 ){ pos.quantity -= 1 notifyItemChanged(position) listener.onDataChanged() // 通知Activity更新 } } holder.pplus.setOnClickListener { pos.quantity += 1 notifyItemChanged(position) listener.onDataChanged() // 通知Activity更新 } }
步骤3:在PosActivity中实现回调
修改Adapter初始化代码,实现接口并更新TextView:
val adapter = MyAdapter(this, selectedItems, object : MyAdapter.OnItemChangeListener { override fun onDataChanged() { total_items_Pos.text = adapter.grandTotal(selectedItems).toString() } })
可选优化:减少重复计算
可以在Adapter内部维护总金额,避免每次遍历列表计算,提升性能:
// MyAdapter中新增变量和方法 private var totalPrice = BigDecimal.ZERO private fun calculateTotal() { totalPrice = BigDecimal.ZERO selectedItems.forEach { item -> totalPrice += item.unitPrice.multiply(item.quantity.toBigDecimal()) } } fun getTotal(): BigDecimal { return totalPrice } // 按钮点击时先更新总价再触发回调 holder.pclose.setOnClickListener { selectedItems.removeAt(position) notifyDataSetChanged() notifyItemRangeChanged(position, selectedItems.size) calculateTotal() listener.onDataChanged() } // 增减按钮同理...
然后Activity中直接调用getTotal():
override fun onDataChanged() { total_items_Pos.text = adapter.getTotal().toString() }
这样就能实现按钮操作时实时更新Activity中的TextView了。
内容的提问来源于stack exchange,提问作者Abbas Amhaz
相关产品推荐
相关产品推荐

