如何遍历 recyclerview 适配器中的项目获取结果并将其传递给片段

Posted

技术标签:

【中文标题】如何遍历 recyclerview 适配器中的项目获取结果并将其传递给片段【英文标题】:How to iterate over items inside a recyclerview adapter get a result and pass it to a fragment 【发布时间】:2021-11-29 19:01:31 【问题描述】:

下面是我的 recyclerview 适配器,每当我的 recyclerview 被填充时,我都会遍历所有视图并计算总收入和支出,并在名为 MainAccountBalance 的变量中获取余额。如何将此变量值传递给我的 Mainfragment,以便我可以在 recyclerview 顶部的 textview 上显示它?任何时候 recyclerview 项目发生变化,或者 recyclerview 填充/重新填充变量都应该在 textview 上自动传递和更新。

对此我很陌生,如果提供 Kotlin 详细代码,将不胜感激。谢谢。

class RecyclerViewAdapter(options: FirestoreRecyclerOptions<DataModel>) : FirestoreRecyclerAdapter<DataModel,  RecyclerViewAdapter.MyViewHolder>(options) 
  private var listener: OnItemClickListener? = null
   private  var MainAccountBalance: Double = 0.00




    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()

        var totalIncome: Double = 0.0
        var totalexpense: Double = 0.0

        // change the money to red or blue based on the transaction type
        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)) 
            totalexpense =model.transaction_amount!! + totalexpense

        
        else 
            holder.amountTextView.setTextColor(Color.parseColor("#3A86FF"))
            holder.amountTextView.text = model.transaction_amount?.let  replaceArabicNumbers(convertIntToCurrencyString(it)) 
            totalIncome = model.transaction_amount!! + totalIncome
        
    MainAccountBalance = totalIncome - totalexpense





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")
        // arabic decimal point = U+066B
        .replace("٫",".")
        // thousands grouping seperator = U+066C
        .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' Time: 'HH:mm")
    return SimpleDateFormat("dd-MM-yyyy")
            .format(systemTime).toString()


fun convertIntToCurrencyString(money :Double): kotlin.String 
    //currency formatter
    val formatter: NumberFormat = DecimalFormat("#,###.##")
    val myNumber = money
    val formattedNumber: kotlin.String = formatter.format(myNumber)

    return formattedNumber
    //currency formatter

【问题讨论】:

@AlexMamo 代码很好,在 onBindViewHolder 我有一个变量“MainAccountBalance”,它的值来自遍历视图,我想将它的值传递给我的片段,recyclerview 所在的位置。我现在不知道该怎么做,我读过实现一个接口是一个解决方案,但是我发现的大多数示例都有 OnClick,在我的情况下,我不需要用户单击以获取“MainAccountBalance”值。非常感谢您的帮助亚历克斯,这是新手,请耐心等待。我正在使用 Kotlin。 【参考方案1】:

因为您使用的是FirestoreRecyclerAdapter 数据会自动更新并且您无法控制它,所以我解释了一些可以帮助您的选项:

在您的适配器类中添加这样的方法:

 fun getAcountBalance():String
   // iterate and update value of MainAccountBalance
   // add a log to check if your calculated value is correct
   return MainAccountBalance.toString() 
 

在您使用此适配器的活动或片段中执行此操作(如果您使用片段,请在 onViewCreated 中执行 onCreate 部分):

    override fun onCreate(savedInstanceState: Bundle?) 
    .....
    
    // difine yourTopTextView before this part

    // initialize your adapter
    val yourAdapter = RecyclerViewAdapter(...)
    //add observer to adapter changes 
    yourAdapter.registerAdapterDataObserver(object : 
    RecyclerView.AdapterDataObserver() 
        // setText the view after any change
        
        override fun onChanged() 
            super.onChanged()
            setTextOfYourView(yourAdapter.getAcountBalance())
        

        override fun onItemRangeChanged(positionStart: Int, itemCount: Int) 
            super.onItemRangeChanged(positionStart, itemCount)
            setTextOfYourView(yourAdapter.getAcountBalance())
        

        override fun onItemRangeChanged(positionStart: Int, itemCount: Int, payload: Any?) 
            super.onItemRangeChanged(positionStart, itemCount, payload)
            setTextOfYourView(yourAdapter.getAcountBalance())
        

        override fun onItemRangeInserted(positionStart: Int, itemCount: Int) 
            super.onItemRangeInserted(positionStart, itemCount)
            setTextOfYourView(yourAdapter.getAcountBalance())
        

        override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) 
            super.onItemRangeRemoved(positionStart, itemCount)
            setTextOfYourView(yourAdapter.getAcountBalance())
        

        override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) 
            super.onItemRangeMoved(fromPosition, toPosition, itemCount)
            setTextOfYourView(yourAdapter.getAcountBalance())

        
    )
    // set adapter to recycler view
    youRecyclerView.adapter= yourAdapter


fun  setTextOfYourView(balnce :String)
    yourTopTextView.setText(balnce)

【讨论】:

衷心感谢 Amir,感谢您抽出宝贵时间编写代码,非常感谢。

以上是关于如何遍历 recyclerview 适配器中的项目获取结果并将其传递给片段的主要内容,如果未能解决你的问题,请参考以下文章

如何在MVVM架构中观察RecyclerView适配器中的LiveData?

如何从另一个项目更新recyclerview项目中的数据?

如何将数据从 RecyclerView 传递到 Kotlin 中的 DialogFragment?

从 Fragment 中的适配器(recyclerview)获取所有项目

如何维护适配器类中recyclerview项目的可见性

如何从recyclerview适配器获取选定项目的数量?