首页 > 解决方案 > 在 Android 中滚动时如何坚持适配器位置?

问题描述

问题是,在我的 recyclerview - 适配器中,单击删除按钮,我显示小进度条代替删除按钮。现在假设完成删除过程需要 2 分钟。因此,与此同时,如果用户正在滚动 recyclerview,则正在运行的进度条会交换 position

我怎么能控制它?

流程:单击删除-delete.onClicklistener-在侦听器内部-在活动中通知-调用异步任务-异步任务结果侦听器是onDeleteDataReceived-在适配器类中调用 updateView()-在 updateView() 内部更改可见性。

注意:该特定位置的项目被正确删除,但在滚动回收视图时进度条位置交换

我已经检查了这个答案,但在我的情况下不起作用:为什么 EditText 中的输入值在 RecyclerView 中滚动时会交换其位置?

代码:

适配器类:

public void updateView(int position, RecyclerView.ViewHolder viewHolder) {
        try {
            if (viewHolder.getAdapterPosition() == position) {
                MyViewHolder holder = (MyViewHolder) viewHolder;
                holder.delete.setVisibility(View.VISIBLE);
                holder.progressBar.setVisibility(View.GONE);
                notifyItemRemoved(position);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

@Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
    Events events = eventList.get(position);

    holder.delete.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (listener != null) {
               holder.delete.setVisibility(View.GONE);
                    holder.progressBar.setVisibility(View.VISIBLE);
                    eventList.get(position).isSelected = true;
                    listener.onClicked(position, eventList.get(position).getEventId());
            }
        }
    });

活动:

 @Override
    public void onDeleteDataReceived(Boolean status, int position) {
        stopShimmerLayout();
        if (status) {
            try {
                if (eventsList.get(position).isSelected) {
                    eventsList.remove(position);
                    RecyclerView.ViewHolder viewHolder = recyclerView.findViewHolderForAdapterPosition(position);
                    mAdapter.updateView(position, viewHolder);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            showToast(context, "Failed", Toast.LENGTH_SHORT);
        }
    }

观看视频以获得更好的理解:https ://drive.google.com/open?id=13ZAtnyfGbi2X4JjUTmJsIDy-gt5y51Gr

实施:https ://drive.google.com/open?id=1ePOfZctEO_IhzUM3bFYW3VJKThoVkI6a

这是什么? 为什么每个人都在说同样的事情?我要问的是一切正常。我能够显示正确位置的进度条和删除按钮可见性,并且项目也被用户选择的位置正确删除。问题是在删除时,如果我开始快速滚动,那么运行进度条会交换位置。但是当我再次到达那个位置时,那个项目被删除了。

标签: android

解决方案


我认为这是在RecyclerView. 一个简单的修复可能是保存当前正在删除的项目的位置,并onBindViewHolder根据您存储的位置设置进度微调器。

让我们在类中采用一个额外的变量,Event如此处其他答案中所指出的那样。这是为了跟踪项目删除。

public class Event {
    // ... Your other variables will go here
    public boolean isDeleting = false; // Set the default value to false 
}

现在在onClickListenerofdelete按钮中,更新变量的状态以指示项目是否正在被删除。

@Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
    Events events = eventList.get(position);

    holder.delete.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (listener != null) {
               // We do not need setting the visibility here. The next actions for notifyDataSetChanged will take care of this. 
               // holder.delete.setVisibility(View.GONE);
               // holder.progressBar.setVisibility(View.VISIBLE);
               eventList.get(position).isSelected = true;
               eventList.get(position).isDeleting = true; // Set the variable to true to indicate that the item is being deleted
               listener.onClicked(position, eventList.get(position).getEventId());

               // It is important here to notify the list that the views are changed when the delete button is clicked. Hence call the notifyDataSetChanged
               notifyDataSetChanged();
            }
        }
    });

    // Now let us update the views based on the selection for deletion
    if (eventList.get(position).isDeleting) {
         // The item is being deleted 
         holder.progressBar.setVisibility(View.VISIBLE);
         holder.delete.setVisibility(View.GONE);
    } else {
        // The item is not being deleted (normal case) 
         holder.progressBar.setVisibility(View.GONE);
         holder.delete.setVisibility(View.VISIBLE);            
    }
}

现在从updateView函数中,您需要根据需要设置并再次eventList调用以在.notifyDataSetChangedRecyclerView

public void updateView(int position) {
    // Update the eventList 
    eventList.remove(position); // Remove the item that was deleted by the index
    // Now let the RecyclerView know that the list is updated as one of the items is removed. 
    notifyDataSetChanged();
}

你应该很高兴去!

更新

我无法运行您共享的程序。但是,我有机会研究活动和适配器类。看起来这里还有其他一些问题。

eventList是一个ArrayList不是线程安全的数据结构。您正在尝试删除后台线程中的事件并RecyclerView在该线程上完成删除时更新。因此,当您尝试同时删除多个项目时,您无法真正确保列表会相应更新。

您可能会考虑synchronized删除或使用线程安全的数据结构来避免eventList.


推荐阅读