I have a checkbox and a recyclerview in a layout. In the adapter I created functions: selectAll & unSelectAll. I expect all items to be checked/unchecked whenever checkbox(in fragment layout) is checked/unchecked respectively. However nothing seems to happen? I am not sure if it's the notifyDataSetChanged() that is not working or if am using it wrongly. I have checked every possible solution here but i unable not to find one. Any help is appreciated.
In adapter:
class DetailRecyclerAdapter :
RecyclerView.Adapter<DetailRecyclerAdapter.BindingHolder>() {
var details: List<ApiDetail>? = null
var isSelectedAll: Boolean = true
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BindingHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val binding = ItemDetailBinding.inflate(layoutInflater, parent, false)
return BindingHolder(binding)
}
override fun onBindViewHolder(holder: BindingHolder, position: Int) {
val detail = details?.get(position)
holder.binding.detail = detail
if (isSelectedAll) {
holder.binding.checkBox.isChecked = true
} else if(!isSelectedAll) {
holder.binding.checkBox.isChecked = false
}
}
override fun getItemCount(): Int {
return details?.size ?: 0
}
fun selectAll() {
isSelectedAll = true
notifyDataSetChanged()
}
fun unSelectAll() {
isSelectedAll = false
notifyDataSetChanged()
}
class BindingHolder(var binding: ItemDetailBinding) : RecyclerView.ViewHolder(binding.root)
}
In fragment:
val adapter = DetailRecyclerAdapter()
binding?.checkBox?.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) {
adapter.selectAll()
} else {
adapter.unSelectAll()
}
}
binding?.detailsRecyclerview?.apply {
layoutManager = LinearLayoutManager(context)
adapter = DetailRecyclerAdapter()
}
In Layout:
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/details_recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:overScrollMode="never"
app:search_details="@{viewModel.details}"/>
BindingAdapter
@BindingAdapter(value = ["search_details"])
@JvmStatic
fun RecyclerView.setSearchConditionDetails(apiDetails: ObservableField<List<ApiDetail>>) {
adapter?.apply {
this as DetailRecyclerAdapter
this.details = apiDetails.get()
notifyDataSetChanged()
}
}
This is the problematic code:
binding?.detailsRecyclerview?.apply {
layoutManager = LinearLayoutManager(context)
adapter = DetailRecyclerAdapter()
}
You are effectively creating a 2nd instance of the DetailRecyclerAdapter, i.e. DetailRecyclerAdapter()
instantiated twice.
The code should read:
val detailRecyclerAdapter = DetailRecyclerAdapter()
binding?.checkBox?.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) {
detailRecyclerAdapter.selectAll()
} else {
detailRecyclerAdapter.unSelectAll()
}
}
binding?.detailsRecyclerview?.apply {
layoutManager = LinearLayoutManager(context)
adapter = detailRecyclerAdapter
}
You want to set your detailsRecyclerView.adapter
to the instance you created earlier, not a new instance. I renamed the var from adapter
to detailRecyclerAdapter
to make this clearer.