Android Recyclerview:Notifydatasetchanged() Illegalstateexception

Android RecyclerView : notifyDataSetChanged() IllegalStateException

You should move method 'setOnCheckedChangeListener()' to ViewHolder which is inner class on your adapter.

onBindViewHolder() is not a method that initialize ViewHolder.
This method is step of refresh each recycler item.
When you call notifyDataSetChanged(), onBindViewHolder() will be called as the number of each item times.

So If you notifyDataSetChanged() put into onCheckChanged() and initialize checkBox in onBindViewHolder(), you will get IllegalStateException because of circular method call.

click checkbox -> onCheckedChanged() -> notifyDataSetChanged() -> onBindViewHolder() -> set checkbox -> onChecked...

Simply, you can fix this by put one flag into Adapter.

try this,

private boolean onBind;

public ViewHolder(View itemView) {
super(itemView);
mCheckBox = (CheckBox) itemView.findViewById(R.id.checkboxId);
mCheckBox.setOnCheckChangeListener(this);
}

@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(!onBind) {
// your process when checkBox changed
// ...

notifyDataSetChanged();
}
}

...

@Override
public void onBindViewHolder(YourAdapter.ViewHolder viewHolder, int position) {
// process other views
// ...

onBind = true;
viewHolder.mCheckBox.setChecked(trueOrFalse);
onBind = false;
}

Recyclerview notifyDataSetChanged is not working?

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.

Cannot call this method while RecyclerView is computing a layout or scrolling when try remove item from recyclerview

Below answer worked for me

This is just workaround for the problem.

This usually occurs when you are calling notifyDataSetChanged() on the background thread. So just move notify to UI thread

recyclerView.post(new Runnable()
{
@Override
public void run() {
myadapter.notifyDataSetChanged();
}
});

You use your RecyclerView instance and inside the post method a new Runnable added to the message queue. The runnable will be run on the user interface thread. This is a limit for Android to access the UI thread from background (e.g. inside a method which will be run in a background thread).
for more you run it on UI thread if you needed.

For more you can run it on UI thread, if you needed

 runOnUiThread(new Runnable(){
public void run() {
// UI code goes here
}
});

RecyclerView and notifyDataSetChanged LongClick mismatch

The problem is you're holding your checked state in the ViewHolder itself - you're toggling its checkbox on and off depending on clicks, right?

The way a RecyclerView works is that instead of having a ViewHolder for every single item (like a ListView does), it only creates a handful of them - enough for what's on screen and a few more for scrolling - and recycles those, using them to display different items.

That's what onBindViewHolder is about - when it needs to display the item at position, it hands you a ViewHolder from its pool and says here you go, use that to display this item's details. This is where you do things like setting text, changing images, and setting things like checkbox state to reflect that particular item.


What you're doing is you're not storing the item's state anywhere, you're just setting the checkbox on the view holder. So if you check it, every item that happens to be displayed in that reusable holder object will have its box ticked. That's why you're seeing it pop up on other items - that checked state has nothing to do with the items themselves, just which view holder they all happen to use because of their position in the list.

So instead, you need to keep their checked state somewhere - it could be as simple as a boolean array that matches the length of your item list. Then you just set and get from that when binding your data (displaying it). Working with what you've got:

// all default to false
val itemChecked = BooleanArray(items.size)

override fun onBindViewHolder(holder: Holder, position: Int) {
...
// when displaying the data, refer to the checked state we're holding
holder.binding.checkbox.checked = itemChecked[position]
...
holder.itemView.setOnLongClickListener {
...
// when checking the box, update our checked state
// since we're calling notifyDataSetChanged, the item will be redisplayed
// and onBindViewHolder will be called again (which sets the checkbox)
itemChecked[position] = true
// notifyItemChanged(position) is better here btw, just refreshes this one
notifyDataSetChanged()
...
}
}

java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling

Filter the data in list before passing to Adapter

 ArrayList<Dbbean> list = yourlist; 

Create a filtered list

  ArrayList<Dbbean> filteredList = new ArrayList<>();
for(Dbbean dbean : list){
if(dbean.blename.startsWith("Dev")
filteredList.add(dbean);
}

Pass filtered list to Adapter

EvelistAdapter adapter = new EvelistAdaptr(this,filteredList);
yourRecyclerView.setAdapter(adapter);


Related Topics



Leave a reply



Submit