I'm trying to set a simple collapsing item in my recyclerView. I saw many applications in Java, but only a few in Kotlin. Almost the onClick method is set inside onBindViewHolder like this:
val isExpandable:Boolean = data[position].expandable
holder.subItem.visibility = if(isExpandable) View.VISIBLE else View.GONE
holder.mainItem.setOnClickListener {
data[position].expandable = !data[position].expandable
notifyItemChanged(position)
}
This work very well. But, I read some developers saying that is not good idea apply onClick methods inside onBindViewHolder, and it must be done inside ViewHolder class. As I'm using Kotlin, I applied onClick method in Koltin way, using lambda. like this:
class MyAdapter(val data:List<MyModel>,
val listener:(MyModel)->Unit):RecyclerView.Adapter<MyAdapter.MyViewHolder>() {
class MyViewHolder(itemView:View):RecyclerView.ViewHolder(itemView){
fun bind (data:MyModel,listener: (MyModel) -> Unit) = with(itemView){
...
view.setOnClickListener {listener(data)}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder = MyViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.card_item,parent,false)
)
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.bind(data[position], listener)
}
override fun getItemCount(): Int = data.count()
}
How can I use data[position]
and notifyItemChanged(position)
inside onClick?
Note: with this Kotlin method, in Activity, when I set the Adapter, the data can be accessed like this:
with(my_recycler) {
layoutManager = LinearLayoutManager(this@MainActivity, RecyclerView.VERTICAL, false)
adapter = MyAdapter(it) {
//data can be accessed here according item position
}
}
If you want to access properties in the ViewHolder from your adapter, you can declare the ViewHolder as an Inner class.
inner class MyViewHolder(itemView:View):RecyclerView.ViewHolder(itemView){
fun bind (data:MyModel,listener: (MyModel) -> Unit) = with(itemView){
...
view.setOnClickListener {listener(data)}
}
}
I haven´t tried calling the notifyItemChanged(position) but I would say that if it is going to be inside a click listener, it shouldn't crash. If you call it from outside of the listener and inside of a function that is called upon notifyItemChanged then you probably will get a crash.
Let me know if it works.