Android RecyclerView项删除行为异常

Android RecyclerView项删除行为异常,android,android-recyclerview,itemtouchhelper,Android,Android Recyclerview,Itemtouchhelper,我正在使用它为我的RecyclerView构建一个itemTouchListener。recyclerview中的项目比屏幕上显示的要多(超过10个),因此回收工作开始了。itemtouchHelper处理上下和左右移动。经过两天的努力(将setStableIds设置为true,这会在上下移动视图时导致viewholder视图闪烁),我终于获得了更好的行为。我的代码包含以下关键功能: @Override public int getItemCount() { retu

我正在使用它为我的RecyclerView构建一个itemTouchListener。recyclerview中的项目比屏幕上显示的要多(超过10个),因此回收工作开始了。itemtouchHelper处理上下和左右移动。经过两天的努力(将setStableIds设置为true,这会在上下移动视图时导致viewholder视图闪烁),我终于获得了更好的行为。我的代码包含以下关键功能:

  @Override
    public int getItemCount() {
        return questionlist.size();
    }

    @Override
    public void onViewMoved(int oldPosition, int newPosition) {
        targetqueobj = questionlist.get(oldPosition);

        this.fromPosition = oldPosition;
        this.toPosition = newPosition;
        questionlist.remove(targetqueobj);
        questionlist.add(newPosition, targetqueobj);

        //    targetqueobj.setinturn(toPosition+1);
    }



    @Override
    public void onViewSwiped(final RecyclerView.ViewHolder thisviewholder,final int position, int direction) {
        targetqueobj = questionlist.get(position);
        if (direction == ItemTouchHelper.LEFT){
            // saveqset();
            Intent intent = new Intent(context, QuestionEditActivity.class);
            intent.putExtra("com.logictop.mqapp.QuestionObjParcelable",targetqueobj);
            context.startActivity(intent);
        }
        if (direction == ItemTouchHelper.RIGHT) {
            // DIALOG
            AlertDialog.Builder builder = new AlertDialog.Builder(context);
            builder.setMessage(R.string.remove_question);
            builder.setNegativeButton(R.string.No, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface arg0, int arg1) {
             //       thisviewholder.itemView.setAlpha(1);
                    notifyDataSetChanged();
                }
            });

            builder.setPositiveButton(R.string.Yes, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface arg0, int arg1) {
                    questionlist.remove(position);
                    notifyItemRemoved(position);
                    notifyItemRangeChanged(position, getItemCount()-position);
                }
            });
            Dialog dialog = builder.create();
            dialog.setCancelable(false);
            dialog.setCanceledOnTouchOutside(false);
            dialog.show();

        }
    }
    if (direction == ItemTouchHelper.RIGHT) {
        // DIALOG
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setMessage(R.string.remove_question);
        builder.setNegativeButton(R.string.No, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface arg0, int arg1) {
                thisviewholder.itemView.setAlpha(1);
                notifyDataSetChanged();
            }
        });

        builder.setPositiveButton(R.string.Yes, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface arg0, int arg1) {
                questionlist.remove(position);
                notifyItemRemoved(position);
                notifyItemRangeChanged(position, getItemCount()-position);
            }
        });
        Dialog dialog = builder.create();
        dialog.setCancelable(false);
        dialog.setCanceledOnTouchOutside(false);
        dialog.show();

    }
}
问题是这个。尽管recyclerview运行平稳,项目的位置变化非常好,但当一个项目被刷走时,有时在向下滚动recyclerview时,另一个项目看起来也被删除了(因此,在滚动后,被删除的另一个项目似乎填充了recyclerview中相同的“屏幕”位置)。这并不是每次都会发生,它主要发生在某些特定位置的视图被刷走时。如果我向上或向下移动邻居的视图,则可以修复该“间隙”

我已经尝试了我在这里找到的每个解决方案(notifyDataChanged、notifyItemRangeChanged(每个参数都是compination)。但是没有任何东西可以让我有一个稳定的行为。在进行了大量stackoverflow搜索之后,我决定遵循
holder.setIsRecyclable(false)
尽管我不想这样做(因为它毕竟消除了使用recyclerview的必要性)。但在这种情况下,会出现其他问题。您将在下面看到,当大多数视图被刷走时,较低的视图不会离开屏幕,即使它们显然“离开了适配器”(无法刷走它们).最后,最后的视图仍然被卡住

我在一个全新的项目上测试了这两种方法,没有任何外部因素的干扰。我尝试将
notifyDataChanged()
放入clearView的重写函数中。似乎没有任何东西能够提供一个坚如磐石的稳定的recyclerview,它本身在某个点上不会有缺口

现在的问题是:有没有一种方法可以让一个正在工作的recyclerview表现得像它应该表现的那样,或者我应该接受这种情况? 非常感谢您的关注

更新1-------------------- 正如我被告知的,这个
thisviewholder.itemView.setAlpha(1);
可能有问题,我把它和相应的覆盖onchildraw(全部)一起注释掉了。当它被刷出时,用来淡出视图。所以现在没有什么是不可见的。问题仍然存在

更新2-------------------- 我实施了stableIds(已经实施过一次,但没有效果)

和适配器构造函数

public QSetEditAdapter(ArrayList<QuestionObj_prcl> questionlist, Context context) {
        this.context = context;
        this.questionlist = questionlist;
        setHasStableIds(true);
    }
公共QSetEditAdapter(ArrayList问题列表,上下文){ this.context=上下文; this.questionlist=问题列表; setHasStableIds(true); } 但问题依然存在

更新3-------------------- 我最终使用了a,现在一切正常。非常感谢!

通过以下方式更改您的设置:

  • 设置为true

  • 实现并返回项目的唯一ID


    • 我不知道为什么会发生这种情况 正是在列表下面的方法中,它保留您第一次给它的值,并且不更新此值

      打开视图时公共无效(内部位置)

      但解决办法是什么??? 解决方案是使用->touchHelper.startSwipe(holder)方法 例如:

      holder.itemView.setOnTouchListener(新的View.OnTouchListener(){ VerOverride 公共布尔onTouch(视图、运动事件){ if(event.getAction()==MotionEvent.ACTION\u向下){ 更新=假; touchHelper.startSwipe(支架); } 返回true; } }))

      此方法的任务是重新加载已删除的动画和视图
      祝您好运

      显然您没有将
      Adapter.bindViewHolder
      中的ViewHolder恢复为默认状态(显然我指的是
      thisviewholder.itemView.setAlpha(1);
      )…这就是为什么在一个叫srijith@Selvin将ViewHolder恢复为默认状态是什么意思?我想不是onPause和onResume之类的东西,对吧?因为我没有提到任何此类问题(因为问题出现在早期阶段,所以没有尝试过)。是否很明显:ViewHolder存储视图…视图具有一些状态,如文本属性…文本颜色等。如果在onBindView外部触摸它(属性),则也需要在onBindView内部将其值还原为默认值(显然我指的是thisviewholder.itemView.setAlpha(1);)您所引用的代码段(
      thisviewholder.itemView.setAlpha(1);
      )用于当用户拒绝删除该项目时,因此该项目必须恢复其alpha值(如果您查看教程,您将看到它覆盖了
      onchildraw
      ,并将视图上的alpha值变为零)。但我不是指当用户选择“否”时会发生什么(还没有捕捉到这一点)。有问题的是“是”(至少现在是这样)。如果是“是”
      builder.setPositiveButton(R.string.yes,new DialogInterface.OnClickListener(){public void onClick(DialogInterface arg0,int arg1){questionlist.remove(position);notifyItemRemoved(position);notifyItemRangeChanged(position,getItemCount()-position);}});
      和“间隙”是不可见的项,正如我在第一条注释中所写的,在bindViewHolder中这样做是安全的,所以当适配器绑定新视图时,它将恢复其alpha
      public QSetEditAdapter(ArrayList<QuestionObj_prcl> questionlist, Context context) {
              this.context = context;
              this.questionlist = questionlist;
              setHasStableIds(true);
          }