在RecyclerView上执行Android操作

时间:2015-04-13 21:35:46

标签: java android adapter android-volley android-viewholder

我最近在使用RecyclerView和Android 5+中ViewHolder的概念时玩了一些。适配器实现处理相当大的数据集(即约60 000项),在 onBindViewHolder(...)调用时从Internet请求。网络请求由排球库处理,响应表示用于填充视图持有者的数据模型。

现在当快速投掷时(即速度不同于用户触摸设备并在屏幕上缓慢移动的滑动),适配器中所有位置都会调用 onBindViewHolder ,因为动画的高速度,大多数视图都不可见,所以这不是一件好事。例如,如果用户在几秒钟内从位置5滑动到300,则大多数视图无法读取,但调用绑定方法。由于适配器从网络获取数据模型 - 会产生大量请求,其中大部分都没有用,并且孔过程只会延迟处理位置300周围的请求,这是用户可以真正观察到的。 / p>

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

我真正的问题是,你将如何解决这个问题?

1 个答案:

答案 0 :(得分:0)

是的,我已经设法通过保持每个适配器位置的状态来解决我的问题。 RecyclerView.Adapter有两种方法onViewAttachedToWindow(VH holder)onViewDetachedFromWindow(VH holder)在用户即将看到视图或者删除视图时发出信号,以便用户看不到它。

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

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

在适配器类中:

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

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

当然这是一个简单的解决方案。可以通过添加线程安全性(即使用Collection.synchronizedSet(...)或使方法同步)或仅使用其他模式来改进代码。 Java大师并没有真正挖掘单例模式。

无论如何,一般的想法是使用onViewAttachedToWindowonViewDetachFromWindow