如何将RecyclerView Adapter计算的账户余额传递至Fragment并自动更新(Kotlin)
解决方案
你原有代码中存在逻辑错误:onBindViewHolder是单个条目绑定时触发的方法,其中定义的totalIncome和totalexpense是单次调用的局部变量,最终得到的MainAccountBalance仅为当前条目的收支差,并非所有条目的总余额。
我们可以通过接口回调的方式实现余额实时同步到Fragment,完整实现如下:
步骤1:修改RecyclerViewAdapter代码
新增余额更新回调接口,在Firestore数据变更的系统回调中遍历所有条目计算总余额,再通过回调抛出结果:
class RecyclerViewAdapter(options: FirestoreRecyclerOptions<DataModel>) : FirestoreRecyclerAdapter<DataModel, RecyclerViewAdapter.MyViewHolder>(options) { private var listener: OnItemClickListener? = null // 新增:余额更新回调接口 interface OnBalanceUpdateListener { fun onBalanceUpdated(balance: Double) } private var balanceListener: OnBalanceUpdateListener? = null // 新增:设置余额更新监听器的方法 fun setOnBalanceUpdateListener(listener: OnBalanceUpdateListener?) { this.balanceListener = listener } // 重写:Firestore数据变更时自动触发的回调 override fun onDataChanged() { super.onDataChanged() var totalIncome = 0.0 var totalExpense = 0.0 // 遍历所有条目计算总收支 for (item in snapshots) { if (item.transaction_type == "expense") { totalExpense += item.transaction_amount ?: 0.0 } else { totalIncome += item.transaction_amount ?: 0.0 } } val mainAccountBalance = totalIncome - totalExpense // 将计算完成的余额通过回调抛出 balanceListener?.onBalanceUpdated(mainAccountBalance) } override fun onBindViewHolder(holder: MyViewHolder, position: Int, model: DataModel) { holder.noteTextView.setText(model.transaction_note) holder.transactionDateTextView.setText(model.transaction_timestamp?.let { convertLongToDateString(it) }).toString() // 删去原这里的总收支计算逻辑,仅保留单条目展示逻辑 val transaction_type = model.transaction_type if (transaction_type=="expense") { holder.amountTextView.setTextColor(Color.parseColor("#D12E9A")) holder.amountTextView.text = model.transaction_amount?.let { replaceArabicNumbers(convertIntToCurrencyString(it)) } } else { holder.amountTextView.setTextColor(Color.parseColor("#3A86FF")) holder.amountTextView.text = model.transaction_amount?.let { replaceArabicNumbers(convertIntToCurrencyString(it)) } } } // 以下原有代码保持不变 public fun replaceArabicNumbers(original: kotlin.String): kotlin.String { return original .replace("٠","0") .replace("١","1") .replace("٢","2") .replace("٣","3") .replace("٤","4") .replace("٥","5") .replace("٦","6") .replace("٧","7") .replace("٨","8") .replace("٩","9") .replace("٫",".") .replace("٬",",") } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder { val v: View = LayoutInflater.from(parent.context).inflate(R.layout.recyclerview_main_account_item, parent, false) return MyViewHolder(v) } fun deleteItem(position: Int) { snapshots.getSnapshot(position).reference.delete() } inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { var transactionDateTextView: TextView var noteTextView: TextView var amountTextView: TextView init { transactionDateTextView = itemView.findViewById(R.id.transactionDateTextView) noteTextView = itemView.findViewById(R.id.noteTextView) amountTextView = itemView.findViewById(R.id.amountTextView) itemView.setOnClickListener { val position = adapterPosition if (position != RecyclerView.NO_POSITION && listener != null) { listener!!.onItemClick(snapshots.getSnapshot(position), position) } } } } interface OnItemClickListener { fun onItemClick(documentSnapshot: DocumentSnapshot?, position: Int) } fun setOnItemClickListener(listener: OnItemClickListener?) { this.listener = listener } fun convertLongToDateString(systemTime: Long): kotlin.String { return SimpleDateFormat("dd-MM-yyyy") .format(systemTime).toString() } fun convertIntToCurrencyString(money :Double): kotlin.String { val formatter: NumberFormat = DecimalFormat("#,###.##") return formatter.format(money) } }
onDataChanged方法会在首次加载数据、条目增删改、列表刷新时自动触发,完全满足你要求的自动更新场景。
步骤2:在MainFragment中接收余额更新
实现余额回调接口,拿到结果后更新顶部TextView即可:
class MainFragment : Fragment() { private lateinit var adapter: RecyclerViewAdapter // 你布局中RecyclerView顶部展示余额的TextView private lateinit var balanceTextView: TextView private lateinit var yourRecyclerView: RecyclerView override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // 初始化控件 balanceTextView = view.findViewById(R.id.your_balance_textview_id) yourRecyclerView = view.findViewById(R.id.your_recyclerview_id) yourRecyclerView.layoutManager = LinearLayoutManager(context) // 原有Firestore查询逻辑保持不变 val yourQuery = FirebaseFirestore.getInstance().collection("your_transaction_collection") val options = FirestoreRecyclerOptions.Builder<DataModel>() .setQuery(yourQuery, DataModel::class.java) .build() // 初始化Adapter adapter = RecyclerViewAdapter(options) // 设置余额更新监听 adapter.setOnBalanceUpdateListener(object : RecyclerViewAdapter.OnBalanceUpdateListener { override fun onBalanceUpdated(balance: Double) { // 格式化后更新TextView val formatted = adapter.replaceArabicNumbers(adapter.convertIntToCurrencyString(balance)) balanceTextView.text = "账户余额:$formatted" } }) // 原有条目点击逻辑保持不变 adapter.setOnItemClickListener(object : RecyclerViewAdapter.OnItemClickListener { override fun onItemClick(documentSnapshot: DocumentSnapshot?, position: Int) { // 你原有的点击处理逻辑 } }) yourRecyclerView.adapter = adapter // 开启Firestore数据监听 adapter.startListening() } override fun onDestroyView() { super.onDestroyView() // 停止Firestore数据监听 adapter.stopListening() } }
内容的提问来源于stack exchange,提问作者Rashid
相关产品推荐
相关产品推荐

