我正在尝试使用notifyDataSetChanged()更新recycleview的项目.
这是我在recycleview适配器中的onBindViewHolder()方法.
@Override public void onBindViewHolder(ViewHolder viewHolder, int position) { //checkbox view listener viewHolder.getCheckbox().setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { //update list items notifyDataSetChanged(); } }); }
我选中一个复选框后,我想要做的是更新列表项.我得到了一个非法的例外:"Cannot call this method while RecyclerView is computing a layout or scrolling"
java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling at android.support.v7.widget.RecyclerView.assertNotInLayoutOrScroll(RecyclerView.java:1462) at android.support.v7.widget.RecyclerView$RecyclerViewDataObserver.onChanged(RecyclerView.java:2982) at android.support.v7.widget.RecyclerView$AdapterDataObservable.notifyChanged(RecyclerView.java:7493) at android.support.v7.widget.RecyclerView$Adapter.notifyDataSetChanged(RecyclerView.java:4338) at com.app.myapp.screens.RecycleAdapter.onRowSelect(RecycleAdapter.java:111)
我也使用了notifyItemChanged(),同样的例外.任何秘密的更新方式,以通知适配器的东西发生了变化?
找到一个简单的解决方
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{ private RecyclerView mRecyclerView; @Override public void onAttachedToRecyclerView(RecyclerView recyclerView) { super.onAttachedToRecyclerView(recyclerView); mRecyclerView = recyclerView; } private CompoundButton.OnCheckedChangeListener checkedChangeListener = (compoundButton, b) -> { final int position = (int) compoundButton.getTag(); // This class is used to make changes to child view final Event event = mDataset.get(position); // Update state of checkbox or some other computation which you require event.state = b; // we create a runnable and then notify item changed at position, this fix crash mRecyclerView.post(new Runnable() { @Override public void run() { notifyItemChanged(position)); } }); } }
在这里,我们为recyclerview准备好处理它时创建一个可运行的notifyItemChanged.
当您有消息错误时:
Cannot call this method while RecyclerView is computing a layout or scrolling
简单,只需执行导致异常的原因:
RecyclerView.post(new Runnable() { @Override public void run() { /** ** Put Your Code here, exemple: **/ notifyItemChanged(position); } });
您应该将方法'setOnCheckedChangeListener()'移动到ViewHolder,它是适配器上的内部类.
onBindViewHolder()
不是初始化的方法ViewHolder
.此方法是刷新每个回收物品的步骤.当你打电话时notifyDataSetChanged()
,onBindViewHolder()
会被称为每个项目的次数.
因此,如果您notifyDataSetChanged()
输入onCheckChanged()
并初始化checkBox onBindViewHolder()
,则由于循环方法调用,您将获得IllegalStateException.
单击复选框 - > onCheckedChanged() - > notifyDataSetChanged() - > onBindViewHolder() - >设置复选框 - > onChecked ...
简单地说,你可以通过在Adapter中放一个标志来解决这个问题.
试试这个,
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; }
我不太清楚,但我也有同样的问题.我通过使用来解决这个onClickListner
问题checkbox
viewHolder.mCheckBox.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub if (model.isCheckboxBoolean()) { model.setCheckboxBoolean(false); viewHolder.mCheckBox.setChecked(false); } else { model.setCheckboxBoolean(true); viewHolder.mCheckBox.setChecked(true); } notifyDataSetChanged(); } });
试试这个,这可能会有所帮助!
protected void postAndNotifyAdapter(final Handler handler, final RecyclerView recyclerView, final RecyclerView.Adapter adapter) { handler.post(new Runnable() { @Override public void run() { if (!recyclerView.isComputingLayout()) { adapter.notifyDataSetChanged(); } else { postAndNotifyAdapter(handler, recyclerView, adapter); } } }); }
您可以在进行更改之前重置上一个侦听器,但不会出现此异常.
private CompoundButton.OnCheckedChangeListener checkedListener = new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { //Do your stuff });; @Override public void onBindViewHolder(final ViewHolder holder, final int position) { holder.checkbox.setOnCheckedChangeListener(null); holder.checkbox.setChecked(condition); holder.checkbox.setOnCheckedChangeListener(checkedListener); }