RecyclerView的已删除行仍然会收到点击事件?

时间:2019-09-27 11:17:30

标签: android android-recyclerview

我有一个RecyclerView,显示项目列表。每行的ViewHolder包含一个删除按钮,用于删除该行。如果我删除最后一行并在消失的行上快速点击,我的应用将崩溃,因为第二次点击事件已传递到删除的行。我很惊讶android提供了第二个事件。在尝试向boolean isDeleted子类中添加类似ViewHolder之类的内容之前,我想知道:在这种情况下,我是否在做其他错误的事情?

class MyAdapter extends RecyclerView.Adapter<MyViewHolder> 
                implements ItemTouchHelperAdapter {

    List<Segment> segments;
    MyAdapter(List<Segment> objs) {
        this.segments = objs;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LinearLayout v = (LinearLayout) LayoutInflater.from(parent.getContext())
                .inflate(R.layout.segment_edit_row, parent, false);
        MyViewHolder vh = new MyViewHolder(v);
        return vh;
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        Segment seg = segments.get(position);
        holder.textView.setText(seg.getTitle());

        holder.dragHandle.setOnTouchListener((v, event) -> {
            if (MotionEventCompat.getActionMasked(event) ==
                    MotionEvent.ACTION_DOWN) {
                onStartDrag(holder);
            }
            return false;
        });
        holder.deleteButton.setOnClickListener(v -> {                
            segments.remove(position);
            notifyItemRemoved(position);
        });

        View.OnClickListener editExerciseListener = v -> {                
            Segment segment = segments.get(position);
            startEditSegmentActivity(segment, position);
        };

        holder.textView.setOnClickListener(editExerciseListener);
        holder.arrow.setOnClickListener(editExerciseListener);
    }

deleteButton处理程序首先运行,然后运行editExerciseListener,而position现已超出范围。

更新

几个人建议我打电话给notifyDataSetChanged。如果您可以通过调用notifyItemRemoved来描述更改,则Android文档特别建议不要这样做。

https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html#notifyDataSetChanged()

那些文档错了吗?

4 个答案:

答案 0 :(得分:1)

每次执行删除操作时,您都必须重新加载recyclerview: 您可以通过添加以下行来完成此操作:

select value, min(fromdate) as fromdate, max(todate) as todate
from (select t.*,
             sum(case when prev_todate >= dateadd(day, -1, fromdate)
                      then 0   -- overlap, so this does not begin a new group
                      else 1   -- no overlap, so this does begin a new group
                 end) over
                 (partition by value order by fromdate) as grp
      from (select t.*,
                   max(todate) over (partition by value
                                     order by fromdate
                                     rows between unbounded preceding and 1 preceding
                                    ) as prev_todate
            from t
           ) t
     ) t
 group by value, grp
 order by value, min(fromdate);

答案 1 :(得分:0)

将代码更新为:

    View.OnClickListener editExerciseListener = v -> {  

            if(position >= segments.size()){
              //index not exists
            }else{
              // index exists
            Segment segment = segments.get(position);
            startEditSegmentActivity(segment, position);
            }              

        };

答案 2 :(得分:0)

首次通话notifyItemRemoved(position);

然后致电segments.remove(position);

答案 3 :(得分:0)

前一段时间,我遇到了类似情况。当我单击recyclerview项目时,该应用程序崩溃了,而该项目正在被删除并且正在进行删除动画(不到一秒钟)。在这种情况下,您的应用容易遭受潜在崩溃的持续时间非常短。

我做什么:

当应用崩溃时,我记录了position(holder.getAdapterPosition())的值。令人惊讶的是,每次发生崩溃时,该值为-1。最终,我编写了一个自定义版本的notifyItemRemoved。在这里:

private void notifyItemRemovedModified(int pos_removed){
    if(pos_removed!=-1){
        // your list is your list
        yourList.remove(pos_removed);
        notifyItemRemoved(pos_removed);
    }
}