Recycler View Callback To Activity
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"