Android RecycledViewPool
01.RecycledViewPool
RecycledViewPool
- RecyclerViewPool用于多个RecyclerView之间共享View。只需要创建一个RecyclerViewPool实例,然后调用RecyclerView的setRecycledViewPool(RecycledViewPool)方法即可。RecyclerView默认会创建一个RecyclerViewPool实例。
- 下列源码,是我借助于有道词典翻译部分注释内容……
- 看出mScrap是一个<viewType, List>的映射,mMaxScrap是一个<viewType, maxNum>的映射,这两个成员变量代表可复用View池的基本信息。调用setMaxRecycledViews(int viewType, int max)时,当用于复用的mScrap中viewType对应的ViewHolder个数超过maxNum时,会从列表末尾开始丢弃超过的部分。调用getRecycledView(int viewType)方法时从mScrap中移除并返回viewType对应的List的末尾项
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108public static class RecycledViewPool {
private static final int DEFAULT_MAX_SCRAP = 5;
static class ScrapData {
final ArrayList<ViewHolder> mScrapHeap = new ArrayList<>();
int mMaxScrap = DEFAULT_MAX_SCRAP;
long mCreateRunningAverageNs = 0;
long mBindRunningAverageNs = 0;
}
SparseArray<ScrapData> mScrap = new SparseArray<>();
private int mAttachCount = 0;
//丢弃所有视图
public void clear() {
for (int i = 0; i < mScrap.size(); i++) {
ScrapData data = mScrap.valueAt(i);
data.mScrapHeap.clear();
}
}
//设置丢弃前要在池中持有的视图持有人的最大数量
public void setMaxRecycledViews(int viewType, int max) {
ScrapData scrapData = getScrapDataForType(viewType);
scrapData.mMaxScrap = max;
final ArrayList<ViewHolder> scrapHeap = scrapData.mScrapHeap;
while (scrapHeap.size() > max) {
scrapHeap.remove(scrapHeap.size() - 1);
}
}
//返回给定视图类型的RecycledViewPool所持有的当前视图数
public int getRecycledViewCount(int viewType) {
return getScrapDataForType(viewType).mScrapHeap.size();
}
//从池中获取指定类型的ViewHolder,如果没有指定类型的ViewHolder,则获取{@Codenull}
@Nullable
public ViewHolder getRecycledView(int viewType) {
final ScrapData scrapData = mScrap.get(viewType);
if (scrapData != null && !scrapData.mScrapHeap.isEmpty()) {
final ArrayList<ViewHolder> scrapHeap = scrapData.mScrapHeap;
return scrapHeap.remove(scrapHeap.size() - 1);
}
return null;
}
//池持有的视图持有者总数
int size() {
int count = 0;
for (int i = 0; i < mScrap.size(); i++) {
ArrayList<ViewHolder> viewHolders = mScrap.valueAt(i).mScrapHeap;
if (viewHolders != null) {
count += viewHolders.size();
}
}
return count;
}
//向池中添加一个废视图保存器。
//如果那个ViewHolder类型的池已经满了,它将立即被丢弃。
public void putRecycledView(ViewHolder scrap) {
final int viewType = scrap.getItemViewType();
final ArrayList<ViewHolder> scrapHeap = getScrapDataForType(viewType).mScrapHeap;
if (mScrap.get(viewType).mMaxScrap <= scrapHeap.size()) {
return;
}
if (DEBUG && scrapHeap.contains(scrap)) {
throw new IllegalArgumentException("this scrap item already exists");
}
scrap.resetInternal();
scrapHeap.add(scrap);
}
long runningAverage(long oldAverage, long newValue) {
if (oldAverage == 0) {
return newValue;
}
return (oldAverage / 4 * 3) + (newValue / 4);
}
void factorInCreateTime(int viewType, long createTimeNs) {
ScrapData scrapData = getScrapDataForType(viewType);
scrapData.mCreateRunningAverageNs = runningAverage(
scrapData.mCreateRunningAverageNs, createTimeNs);
}
void factorInBindTime(int viewType, long bindTimeNs) {
ScrapData scrapData = getScrapDataForType(viewType);
scrapData.mBindRunningAverageNs = runningAverage(
scrapData.mBindRunningAverageNs, bindTimeNs);
}
boolean willCreateInTime(int viewType, long approxCurrentNs, long deadlineNs) {
long expectedDurationNs = getScrapDataForType(viewType).mCreateRunningAverageNs;
return expectedDurationNs == 0 || (approxCurrentNs + expectedDurationNs < deadlineNs);
}
boolean willBindInTime(int viewType, long approxCurrentNs, long deadlineNs) {
long expectedDurationNs = getScrapDataForType(viewType).mBindRunningAverageNs;
return expectedDurationNs == 0 || (approxCurrentNs + expectedDurationNs < deadlineNs);
}
void attach(Adapter adapter) {
mAttachCount++;
}
void detach() {
mAttachCount--;
}//分离旧适配器并附加新适配器。如果它只附加了一个适配器,并且新适配器使用与oldAdapter不同的ViewHolder, //则RecycledViewPool将清除其缓存。 void onAdapterChanged(Adapter oldAdapter, Adapter newAdapter,boolean compatibleWithPrevious) { if (oldAdapter != null) { detach(); } if (!compatibleWithPrevious && mAttachCount == 0) { clear(); } if (newAdapter != null) { attach(newAdapter); } } private ScrapData getScrapDataForType(int viewType) { ScrapData scrapData = mScrap.get(viewType); if (scrapData == null) { scrapData = new ScrapData(); mScrap.put(viewType, scrapData); } return scrapData; }
}
1
2
3
4
5
- ViewCacheExtension
- ViewCacheExtension是一个由开发者控制的可以作为View缓存的帮助类。调用Recycler.getViewForPosition(int)方法获取View时,Recycler先检查attachedscrap和一级缓存,如果没有则检查ViewCacheExtension.getViewForPositionAndType(Recycler, int, int),如果没有则检查RecyclerViewPool。注意:Recycler不会在这个类中做缓存View的操作,是否缓存View完全由开发者控制。
public abstract static class ViewCacheExtension {
abstract public View getViewForPositionAndType(Recycler recycler, int position, int type);
}
```