fix(adapter): 修复 ScaleRowAdapter 点击事件偶发失效,改用同步更新替代 submitList

- 新增 updateItem / updateName / removeByAddress 同步更新方法,使用 set/add/removeAt 直接触发 notifyItemChanged
- 新增 onItemClick lambda 属性,点击时通过 bindingAdapterPosition 取最新数据
- SlaveActivity 中所有 submitList 调用替换为对应同步方法,消除 AsyncListDiffer 异步窗口期导致的点击丢失

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-06 10:01:19 +08:00
co-authored by Claude Sonnet 4.6
parent e990652981
commit 12c6b5cf94
2 changed files with 54 additions and 27 deletions
@@ -3,6 +3,7 @@ package com.shuwei.dish.match.adapter
import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.chad.library.adapter4.BaseQuickAdapter
import com.chad.library.adapter4.viewholder.QuickViewHolder
import com.shuwei.dish.match.databinding.ListItemScaleRowBinding
@@ -11,6 +12,8 @@ import com.shuwei.dish.match.utils.WeightUtil
/**
* 线性列表秤数据 Adapter
* 用于 SlaveActivity 非22/18格子设备的秤列表展示
* 通过 updateItem / updateName / removeByAddress 同步更新,避免 submitList 的
* AsyncListDiffer 异步窗口期导致点击事件丢失
*/
class ScaleRowAdapter : BaseQuickAdapter<ScaleRowAdapter.ScaleItem, ScaleRowAdapter.VH>() {
@@ -23,6 +26,9 @@ class ScaleRowAdapter : BaseQuickAdapter<ScaleRowAdapter.ScaleItem, ScaleRowAdap
*/
data class ScaleItem(val address: Int, val weight: Double, val state: Int, val name: String = "")
/** item 点击回调 */
var onItemClick: ((ScaleItem) -> Unit)? = null
inner class VH(val b: ListItemScaleRowBinding) : QuickViewHolder(b.root)
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH {
@@ -40,5 +46,48 @@ class ScaleRowAdapter : BaseQuickAdapter<ScaleRowAdapter.ScaleItem, ScaleRowAdap
WeightUtil.STATE_OVER_WEIGHT -> "超量"
else -> "${item.state}"
}
// 点击时通过 bindingAdapterPosition 取最新数据,避免闭包捕获过期 item
holder.b.root.setOnClickListener {
val pos = holder.bindingAdapterPosition
if (pos != RecyclerView.NO_POSITION) {
items.getOrNull(pos)?.let { onItemClick?.invoke(it) }
}
}
}
/**
* 同步更新单条秤数据:存在则定点刷新,不存在则按 address 升序插入
* 使用 set/add 替代 submitList,消除 AsyncListDiffer 异步窗口期
* @param item 最新秤数据
*/
fun updateItem(item: ScaleItem) {
val idx = items.indexOfFirst { it.address == item.address }
if (idx >= 0) {
set(idx, item)
} else {
// 找到按 address 升序的插入位置
val insertPos = items.indexOfFirst { it.address > item.address }
.let { if (it < 0) items.size else it }
add(insertPos, item)
}
}
/**
* 同步更新指定地址的调料名称
* @param address 秤地址
* @param name 新名称
*/
fun updateName(address: Int, name: String) {
val idx = items.indexOfFirst { it.address == address }
if (idx >= 0) set(idx, items[idx].copy(name = name))
}
/**
* 同步移除指定地址的条目
* @param address 秤地址
*/
fun removeByAddress(address: Int) {
val idx = items.indexOfFirst { it.address == address }
if (idx >= 0) removeAt(idx)
}
}
@@ -125,10 +125,7 @@ class SlaveActivity : BaseActivity() {
else -> {
binding.rvScaleList.updateLayoutParams<LinearLayout.LayoutParams> { topMargin = 20.dp }
binding.rvScaleList.layoutManager = LinearLayoutManager(this)
linearAdapter.setOnItemClickListener { _, _, position ->
val item = linearAdapter.items.getOrNull(position) ?: return@setOnItemClickListener
showTareDialog(item.address)
}
linearAdapter.onItemClick = { item -> showTareDialog(item.address) }
binding.rvScaleList.adapter = linearAdapter
}
}
@@ -203,12 +200,8 @@ class SlaveActivity : BaseActivity() {
if (pos >= 0) scale18Adapter!!.updateItemName(pos, "")
}
else -> {
val list = linearAdapter.items.toMutableList()
val idx = list.indexOfFirst { it.address == addr }
if (idx >= 0) {
list[idx] = list[idx].copy(name = "")
linearAdapter.submitList(list)
}
val idx = linearAdapter.items.indexOfFirst { it.address == addr }
if (idx >= 0) linearAdapter.removeByAddress(addr)
}
}
}
@@ -225,14 +218,7 @@ class SlaveActivity : BaseActivity() {
val pos = ScaleDeviceConfig.SCALE_ORDER_18.indexOf(slot.address)
if (pos >= 0) scale18Adapter!!.updateItemName(pos, slot.goodsName)
}
else -> {
val list = linearAdapter.items.toMutableList()
val idx = list.indexOfFirst { it.address == slot.address }
if (idx >= 0) {
list[idx] = list[idx].copy(name = slot.goodsName)
linearAdapter.submitList(list)
}
}
else -> linearAdapter.updateName(slot.address, slot.goodsName)
}
}
}
@@ -272,15 +258,7 @@ class SlaveActivity : BaseActivity() {
}
else -> {
val item = ScaleRowAdapter.ScaleItem(address, weight, state, slotNameMap[address] ?: "")
val list = linearAdapter.items.toMutableList()
val idx = list.indexOfFirst { it.address == address }
if (idx >= 0) {
list[idx] = item
} else {
list.add(item)
list.sortBy { it.address }
}
linearAdapter.submitList(list)
linearAdapter.updateItem(item)
}
}