Search code examples
androidfirebasekotlinandroid-recyclerviewandroid-viewbinding

Notifydatasetchanged, dialogs and view binding


Scenario

Recently moved from synthetics to view binding and I'm still struggling (haven't done any coding in months, so I'm rusty as it gets).

MainActivity has two recyclerviews, one displaying totals, one displaying a list of transactions. Each transaction has a "OnLongClickListener" attached to it (attached in the adapter class). This listener calls for a MaterialAlertDialog with two options: edit or delete. There's also a separate fragment for adding transactions.

Summary layout and components

Requirement

Upon addition, deletion or modification of these transactions, both recycleradapters need to refresh the data in order to reflect the correct information on screen.

Problem

I'm not able to get the adapters to receive the "notifydatasetchanged" as I am not sure how to get the adapters' reference.

Code being used

MainActivity

    private val db = FirebaseFirestore.getInstance()
    private val dbSettings = firestoreSettings { isPersistenceEnabled = true }
        
    CoroutineScope(Dispatchers.Default).launch {
        val adapterRV1 = Adapter_RV1(FSDB.Get_calculations, FSDB.Get_transactions(db))
        val adapterRV2 = Adapter_RV2(FSDB.Get_transactions(db))

        runOnUiThread {
            binding.rvCalculations.adapter = adapterRV1
            binding.rvTransactions.adapter = adapterRV2
        }
    }

Adapter_RV1

class Adapter_RV1(val calculations_list: List<calculation>,val transactions_list: ArrayList<Transactions>) : RecyclerView.Adapter<Adapter_RV1.CalculationViewHolder>() {

    private lateinit var binding: RvCalculationsLayoutBinding

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Adapter_RV1.CalculationViewHolder {
        val binding = RvCalculationsLayoutBinding
            .inflate(LayoutInflater.from(parent.context), parent, false)
        return CalculationViewHolder(binding)
    }

    override fun onBindViewHolder(holder: KPIViewHolder, position: Int) {

        with(holder) {
            with(calculations_list[position]) {
            ...
            }
        }
    }

    override fun getItemCount() = calculations_list.size

    inner class CalculationViewHolder(val binding: RvCalculationsLayoutBinding) :
        RecyclerView.ViewHolder(binding.root)
}

Adapter_RV2

class Adapter_RV2(var transactions_list: List<Transaction>):
    RecyclerView.Adapter<Adapter_RV2.TransactionsViewHolder>() {

    private lateinit var binding: RvTransactionsLayoutBinding

    inner class TransactionsViewHolder(val binding: RvTransactionsLayoutBinding) : RecyclerView.ViewHolder(binding.root){

        init {
            binding.root.setOnLongClickListener {
                val position = absoluteAdapterPosition
                val item = transactions_list[position]

                CoroutineScope(Dispatchers.Main).launch {
                    CreateDialog(item,position,binding)
                }

                true
            }
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Adapter_RV2.TransactionsViewHolder {
        val binding = RvTransactionsLayoutBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return TransactionsViewHolder(binding)
    }

    override fun onBindViewHolder(holder: TransactionsViewHolder, position: Int) {
        ...
    }

    override fun getItemCount() = transactions_list.size
}

CreateDialog

class CreateDialog (transaction: Transaccion, position: Int, binding: RvVistaTransaccionesBinding){

    private suspend fun DeleteTransaction(position: Int) {
        ...
        traRef.update("transactions", FieldValue.arrayRemove(transaction)).await()
    }

    private val puBinding : PopupLayoutBinding = PopupLayoutBinding.inflate(LayoutInflater.from(binding.root.context))

    init {
        with(puBinding){
            ...
            CoroutineScope(Dispatchers.Main).launch {
                supervisorScope {
                    val task = async {
                        DeleteTransaction(position)
                    }
                    try{
                        task.await()
                        /// This is where, I guess, adapters should be notified of dataset changes
                        popup.dismiss()
                    }
                    catch (e: Throwable){
                        crashy.recordException(e)
                        Log.d("Transaction",e.message!!)
                        popup.dismiss()
                    }
                }
            }
        }
    }

    popup.setView(puBinding.root)
    popup.show()
}

What I've tested so far

I honestly have no clue how to proceed. I've tried a few things but none work and considering I'm super green in Dev in general, View Binding is a bit more confusing than usual.


Solution

  • I have replaced the line below

    notifyDataSetChanged();

    with

    binding.recycler.getAdapter().notifyDataSetChanged();

    in my own code.

    Here, "recyler" is my RecyclerView, and "binding" is ActivityListBinding.

    I didnt read your code, maybe my tip will help you, it worked for me.