Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/206.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Android在RecyclerView上抛出动作_Java_Android_Adapter_Android Volley_Android Viewholder - Fatal编程技术网

Java Android在RecyclerView上抛出动作

Java Android在RecyclerView上抛出动作,java,android,adapter,android-volley,android-viewholder,Java,Android,Adapter,Android Volley,Android Viewholder,我最近在安卓5+上玩了一点RecyclerView和ViewHolder的概念。适配器实现处理相当大的数据集(即约60000项),在调用onBindViewHolder(…)时从internet请求。网络请求由volley库处理,响应表示用于填充视图持有者的数据模型 现在,当快速投掷(即以一定速度移动,不同于用户触摸设备并在屏幕上缓慢移动的滑动)时,适配器中的所有位置都会调用onBindViewHolder,这不是一件好事,因为动画速度太快,大多数ViewHolder都看不见。例如,如果用户在几

我最近在安卓5+上玩了一点RecyclerView和ViewHolder的概念。适配器实现处理相当大的数据集(即约60000项),在调用onBindViewHolder(…)时从internet请求。网络请求由volley库处理,响应表示用于填充视图持有者的数据模型

现在,当快速投掷(即以一定速度移动,不同于用户触摸设备并在屏幕上缓慢移动的滑动)时,适配器中的所有位置都会调用onBindViewHolder,这不是一件好事,因为动画速度太快,大多数ViewHolder都看不见。例如,如果用户在几秒钟内从位置5滑动到300,大多数视图都无法读取,但会调用bind方法。由于适配器从网络获取数据模型,因此发出了很多请求,其中大多数都没有用处,而孔处理只是将请求的处理延迟到位置300左右,这是用户可以真正观察到的位置

如何处理仅要求可见位置的问题? 我的第一种方法是对截取处理队列中的请求进行优先级排序。这并没有解决很多问题,因为每个网络请求都是以不同的顺序处理的。我的第二种方法是在添加新请求时取消所有现有请求。它对我来说不是很好,从设计的角度来看,我不喜欢这个解决方案


我真正的问题是,您将如何处理此问题?

是的,我已通过保持每个适配器位置的状态来解决我的问题。RecyclerView.Adapter有两种方法,分别是当用户即将看到视图或当视图被移除时,发出信号通知视图附加到窗口(VH保持架)和
打开视图从窗口分离(VH保持架)

我创建了一个简单的singleton类来保持每个适配器位置的状态:

import java.util.HashSet;
import java.util.Set;

/**
 * Created by fauri on 14/06/2015.
 */
public class ViewHolderState {
    private static final ViewHolderState ourInstance = new ViewHolderState();
    private Set<Integer> recycled = new HashSet<>();

    private ViewHolderState() {
    }

    public static ViewHolderState getInstance() {
        return ourInstance;
    }

    public void addRecycledView(int position) {
        recycled.add(position);
    }

    public void removeRecycledView(int position) {
        recycled.remove(position);
    }

    public boolean isViewRecycled(int position) {
        return recycled.contains(position);
    }

    public void clearAll() {
        recycled.clear();
    }
}
这只是为了保持每个适配器位置的状态。现在,在触发网络调用的业务逻辑中,您只需获取singleton实例并检查
isViewRecycled(int adapterPosition)
。如果视图被回收,则无需进行网络呼叫

当然,这是一个简单的解决方案。可以通过添加线程安全性(即使用Collection.synchronizedSet(…)或使方法同步化)或仅使用另一种模式来改进代码。Java大师们并不真正喜欢单例模式


总之,总的想法是利用视图上的
附件到窗口
和视图上的
从窗口分离

您对此有什么结论吗?我在使用Volley的NetworkImageView时也遇到同样的问题。
 private ViewHolderState viewHolderState = ViewHolderState.getInstance();


 @Override
    public void onViewDetachedFromWindow(CardViewHolder holder) {
        super.onViewDetachedFromWindow(holder);
        viewHolderState.addRecycledView(holder.getAdapterPosition());
    }

    @Override
    public void onViewAttachedToWindow(CardViewHolder holder) {
        super.onViewAttachedToWindow(holder);
        viewHolderState.removeRecycledView(holder.getAdapterPosition());
    }