在Android中滚动时如何坚持适配器的位置? [英] How stick to with Adapter position while it's scrolling in Android?

查看:46
本文介绍了在Android中滚动时如何坚持适配器的位置?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题是,在我的recyclerview-适配器中,单击删除"按钮,我正在显示小的进度条来代替删除"按钮.现在,假设需要2分钟才能完成删除过程.因此,在平均时间内,如果用户滚动了recyclerview,则运行进度栏交换位置.

The problem is, in my recyclerview - adapter, clicking on delete button, I'm showing small progressbar in place of delete button. Now suppose it is taking 2 minutes to complete the delete process. So in mean time if user is scrolling recyclerview, that running progressbar swaps the position.

我该如何控制?

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

FLOW: Clicked delete - delete.onClicklistener - inside listener - notified in activity - calling async task - asynctask result listener is onDeleteDataReceived - inside called updateView() which is in adapter class - inside updateView() change visibility.

注意:该项目已针对该特定位置正确删除,但在滚动recyclerview时会交换进度栏位置

NOTE: Item is being deleted correctly for that particular position, but progressbar position swaps while scrolling recyclerview

我已经检查了此答案,但在我的情况下不起作用:

I already checked this answer, but not working in my case: Why does the input value in EditText swaps its position while scrolling in a 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

See the video for better understanding: https://drive.google.com/open?id=13ZAtnyfGbi2X4JjUTmJsIDy-gt5y51Gr

实施: https://drive.google.com/open?id=1ePOfZctEO_IhzUM3bFYW3VJKT a>

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

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

WHAT IS THIS? why everyone is telling the same thing? What I'm asking is everything is working correctly. I'm able to show progressbar and delete button visibility for correct position and also item is also being delete correctly by user selected position. The problem is while deleting if I start scrolling very fast that time that running progressbar swaps the position. But that item is deleted in mean time when I again reach that position.

推荐答案

我认为这是在RecyclerView上动态更新视图的非常常见的问题.一个简单的解决方法是保存当前正在删除的项目的位置,并根据您存储的位置在您的onBindViewHolder中设置进度微调器.

I think this is a very usual problem of updating views dynamically on a RecyclerView. A simple fix could be saving the position of the item that is currently being deleted and set the progress spinner in your onBindViewHolder based on the positions that you stored.

让我们在Event类中增加一个额外的变量,如此处其他答案所示.这是为了跟踪项目删除.

Let us take an extra variable in the Event class as pointed in the other answer here. This is to keep track of the item deletion.

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

现在在delete按钮的onClickListener中,更新变量的状态以指示是否要删除该项目.

Now in the onClickListener of delete button, update the status of the variable to indicate if the item is being deleted.

@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,然后再次调用notifyDataSetChanged,以在RecyclerView中获取更新的视图.

Now from the updateView function, you need to set up the eventList as required and call the notifyDataSetChanged again to get the updated views in your RecyclerView.

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();
}

您应该很好!

更新

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

I could not run the program that you shared. However, I had a chance to look into the activity and the adapter class. It looks like there are some other problems here.

eventListArrayList,它不是线程安全的数据结构.您正在尝试删除后台线程中的事件,并在该线程上删除完成后更新RecyclerView.因此,当您尝试同时删除多个项目时,您不能真正确保该列表将被相应地更新.

The eventList is an ArrayList which is not a thread-safe data-structure. You are trying to remove an event in a background thread and updating the RecyclerView when the deletion is complete on that thread. Hence, when you are trying to delete multiple items at the same time, you cannot really ensure that the list will be updated accordingly.

您可能会考虑删除synchronized或使用线程安全的数据结构来避免eventList中的并发修改问题.

You might consider having a synchronized deletion or using a thread-safe data structure to avoid this concurrent-modification problem in your eventList.

这篇关于在Android中滚动时如何坚持适配器的位置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆