Skip to content Skip to sidebar Skip to footer

Recycler View Callback To Activity

I'm trying to implement a click listener for a single recycler view item and run method from my activity with clicked data (single borrower). How to deal with it? I'm new in kotlin

Solution 1:

1) This answer here works both on Kotlin and Java:

How to implement click listener callback

2) Kotlin Only (Lambdas):

In your Adapter: Add a property named listener that is a lambda you pass from your activity or fragment:

classMyAdapter(privateval listener: (position: Int) -> Unit) : RecyclerView.Adapter<MyAdapter.MyViewHolder>() {

    ...

    innerclassMyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {

        init {
            itemView.setOnClickListener(this)
        }

        overridefunonClick(v: View?) {
            listener.invoke(adapterPosition)
            //or listener(adapterPosition)
        }
    }

}

In your Activity/Fragment onCreate() after setting recyclerview's layout manager:

recyclerView.adapter = MyAdapter { position ->//Do anything you like when some item gets click in your adapter you //can use the position
}

Be careful with inner classes as they can lead to a Memory Leak in your app, for more safety you can switch to using Nested classes.

Solution 2:

You could easily do so by adding a callback function to your Borrower.

Given the type:

// UI stands for User InterfacedataclassBorrowerUI(val borrower: Borrower, val onClick: (Borrower) -> Unit)

Then change your RecyclerView.Adapter to receive List<BorrowerUI> instead of List<Borrower>.

After that change a tiny bit your refreshData implementation:

classBorrowersListVh(view: View): RecyclerView.ViewHolder(view) {
    funrefreshData(borrowerUI: BorrowerUI) {
        itemView.borrowersListName.text = borrower.name
        itemView.borrowersLisDebt.text = borrower.debt.toString()

        itemView.setOnClickListener {
            Log.e("info", "Clicked")
            borrowerUI.onClick(borrowerUI.borrower)
        }
    }
}

Finally in your Activity when you create the RecyclerView.Adapter

classYourActivity: AppCompatActivity() {


     overridefunonCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         thread {
              var borrowers = 
                  db.borrowers()
                     .getAll()
                     .map { BorrowerUI(it) { onBorrowerClick(it) } }

              runOnUiThread {
                  val debtsSum = borrowers.sumByDouble { it.debt }

                  // update sum of debts
                  summary.text = debtsSum?.toBigDecimal().setScale(2, 2).toString()
                  // update item list
                 recycler.apply {
                     layoutManager = LinearLayoutManager(this@MainActivity)
                     adapter = BorrowersListAdapter(borrowers)
                 }
               }
         }
     }

     funonBorrowerClick(borrower: Borrower) {
         // Create a toast?
     }
}

Solution 3:

Give your adapter constructor an additional property for a callback that can respond to a Borrower being clicked:

classBorrowersListAdapter(privateval dane: List<Borrower>, val onItemClicked: (Borrower) -> Unit) //...

Then when binding views, you can set a listener on the item view to call the callback with the newly associated Borrower:

overridefunonBindViewHolder(holder: BorrowersListVh, position: Int) {
    val borrower: Borrower = dane[position]
    holder.refreshData(borrower)
    holder.itemView.setOnClickListener {
        onItemClicked(borrower)
    }
}

Then in your Activity, you can create a function that matches the callback function signature. The name doesn't matter.

funonBorrowerClick(borrower: Borrower) {
    Log.i("borrower clicked", borrower.toString())
}

And when you instantiate the adapter, pass this function as the callback to the constructor.

adapter = BorrowersListAdapter(borrowers, ::onBorrowerClick)

Side note, instead of using a thread directly like you are, you should use the lifecycleScope to launch a coroutine so you aren't leaking your Activity to a background thread:

overridefunonCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    addDebtBtn.setOnClickListener {
        startDebtActivity()
    }

    lifecycleScope.launch {
        val borrowers = withContext(Dispatchers.IO) {
            db.borrowers()
                .getAll()
        }

        val debtsSum = borrowers.sumByDouble { it.debt }

        // update sum of debts
        summary.text = debtsSum?.toBigDecimal().setScale(2, 2).toString()
        // update item list
        recycler.apply {
            layoutManager = LinearLayoutManager(this@MainActivity)
            adapter = BorrowersListAdapter(borrowers, ::onBorrowerClick)
        }
    }
}

Post a Comment for "Recycler View Callback To Activity"