当RecyclerView计算布局或滚动时尝试从recyclerview中删除项目时,无法调用此方法

Den*_*wan 32 android android-recyclerview

我正在尝试从recyclerview中删除我的项目,但我总是收到错误

java.lang.IllegalStateException:当RecyclerView正在计算布局或滚动时,无法调用此方法

我正在使用notify datasetchanged,我能解决这个问题吗?

public class AdapterIntransit extends RecyclerView.Adapter<AdapterIntransit.ViewHolder> {
    private Context context;
    List<DataIntransit> data;

    public AdapterIntransit(Context context, List<DataIntransit> data) {
        this.context = context;
        this.data = data;
    }

    @Override
    public AdapterIntransit.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.cardintransit, parent, false);
        return new ViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(AdapterIntransit.ViewHolder holder, int position) {
        if (data.get(position).getJml1() - data.get(position).getJml2() <= 0) {
            data.remove(position);
            notifyItemRemoved(position);
            notifyItemRangeChanged(position, getItemCount());
            notifyDataSetChanged();
        } else {
            holder.kode.setText(data.get(position).getKode());
            holder.nama.setText(data.get(position).getNama());
            holder.jumlah.setText(String.valueOf(data.get(position).getJml1() - data.get(position).getJml2()));
        }
    }

    @Override
    public int getItemCount() {
        return data.size();
    }
    public class ViewHolder extends RecyclerView.ViewHolder{
        TextView kode, nama, jumlah;
        public ViewHolder(View itemView) {
            super(itemView);
            kode = (TextView)itemView.findViewById(R.id.kode);
            nama = (TextView)itemView.findViewById(R.id.nama);
            jumlah = (TextView)itemView.findViewById(R.id.jumlah);

        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Sag*_*gar 47

以下答案对我有用

dialeecyclerView.post(new Runnable()
            {
                @Override
                public void run() {
                myadapter.notifyDataSetChanged();
            }
            });
Run Code Online (Sandbox Code Playgroud)

您使用RecyclerView实例并在post方法中添加一个新的Runnable添加到消息队列中.runnable将在用户界面线程上运行.这是Android UI从后台访问线程的限制(例如,在后台线程中运行的方法内).UI 如果需要,可以在线程上运行它.

UI如果需要,您可以在线程上运行它

 runOnUiThread(new Runnable(){
 public void run() {
      // UI code goes here
 }
 });
Run Code Online (Sandbox Code Playgroud)

  • 这似乎是 RecyclerView 库中的一个错误,当 `notifyDataSetChanged()` 被快速连续(在 50 毫秒内)或在滚动时调用时——即使它是在 `onBindViewHolder()` 之外调用的。例如,当使用 `notifyDataSetChanged()` 刷新整个列表时会发生这种情况,不一定添加或删除项目。`Runnable` 建议效果很好。这里有一个错误报告:https://issuetracker.google.com/issues/37136189 (3认同)
  • 原因之一可能是您的视图持有者中有一个动画视图。也许是一个切换,切换后你调用了`notify...` (2认同)
  • @AndroidGuy 这会起作用,但这不是正确的方法。如果您有开关,并且您手动切换它,请不要通知。开关将自行动画,您就完成了。如果你想以编程方式改变开关的状态,那么你通知,通知后开关就会改变。 (2认同)

Sha*_*aur 14

如果您想通知 recylew 项目,请使用 isComputingLayout 方法:

if (!mRecyclerView.isComputingLayout()) 
{
 // add your code here
}
Run Code Online (Sandbox Code Playgroud)

  • 如果是计算布局那么代码的请求将永远不会完成? (19认同)
  • @ghita:如果是计算,那么你可以使用类似`else {Handler handler = new Handler(Looper.getMainLooper()); 的东西。handler.post(new Runnable() {@Override public void run() {myPagerAdapter.notifyItemRemoved(position);} });}` (或您需要的任何notifyXYZ风格) (2认同)

sne*_*yan 8

onBindViewHolder()当您的项目处于构建过程中时,您正在通知方法内部的项目更改。很可能你可以改进你的逻辑,以避免这种情况。


Cod*_*sed 8

您需要两种方法才能使其工作:

if (!rv.isComputingLayout && rv.scrollState == SCROLL_STATE_IDLE) {
   rv.adapter?.notifyDataSetChanged()
}
Run Code Online (Sandbox Code Playgroud)


小智 7

在recyclerview顶部的复选框上单击以选中“所有”复选框时,这很有用。

recyclerview.post(new Runnable()
{
     @Override
     public void run() {
         myadapter.notifyDataSetChanged();
     }
});
Run Code Online (Sandbox Code Playgroud)