我最近在使用RecyclerView和Android 5+中ViewHolder的概念时玩了一些。适配器实现处理相当大的数据集(即约60 000项),在 onBindViewHolder(...)调用时从Internet请求。网络请求由排球库处理,响应表示用于填充视图持有者的数据模型。
现在当快速投掷时(即速度不同于用户触摸设备并在屏幕上缓慢移动的滑动),适配器中所有位置都会调用 onBindViewHolder ,因为动画的高速度,大多数视图都不可见,所以这不是一件好事。例如,如果用户在几秒钟内从位置5滑动到300,则大多数视图无法读取,但调用绑定方法。由于适配器从网络获取数据模型 - 会产生大量请求,其中大部分都没有用,并且孔过程只会延迟处理位置300周围的请求,这是用户可以真正观察到的。 / p>
如何处理仅请求可见位置的问题? 我的第一种方法是在排球处理队列中优先处理请求。这实际上并没有解决很多问题,因为每个网络请求只是以不同的顺序处理。我的第二种方法是在添加新请求时取消所有现有请求。它对我来说效果不好,从设计的角度来看,我不喜欢这个解决方案。
我真正的问题是,你将如何解决这个问题?
答案 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大师并没有真正挖掘单例模式。
无论如何,一般的想法是使用onViewAttachedToWindow
和onViewDetachFromWindow