-
Notifications
You must be signed in to change notification settings - Fork 7
/
QuickFlowAdapter.java
157 lines (133 loc) · 4.87 KB
/
QuickFlowAdapter.java
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package com.liyi.flow.adapter;
import android.support.annotation.LayoutRes;
import android.util.SparseIntArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
public abstract class QuickFlowAdapter<T, VH extends BaseFlowHolder> extends BaseFlowAdapter<VH> {
private static final int LAYOUT_NOT_FOUND = -404;
private LayoutInflater mLayoutInflater;
private SparseIntArray mLayoutTypes;
protected List<T> mData;
public QuickFlowAdapter() {
}
public void setData(List<T> list) {
this.mData = list;
}
public List<T> getData() {
return mData;
}
public void updateData(List<T> list) {
setData(list);
notifyDataSetChanged();
}
/**
* 添加不同类型的 item 布局
*
* @param type 此处的 type 必须与 getItemViewType() 中返回的 type 对应
* @param layoutId
*/
public void addItemType(int type, @LayoutRes int layoutId) {
if (mLayoutTypes == null) {
mLayoutTypes = new SparseIntArray();
}
mLayoutTypes.put(type, layoutId);
}
@Override
public int getItemViewType(int position) {
return onHandleViewType(position);
}
@Override
public VH onCreateViewHolder(ViewGroup parent, int viewType) {
if (mLayoutInflater == null) mLayoutInflater = LayoutInflater.from(parent.getContext());
View convertView = getItemView(getLayoutId(viewType), parent);
VH holder = createBaseViewHolder(convertView);
return holder;
}
@Override
public void onBindViewHolder(VH holder, int position) {
onHandleViewHolder(holder, position, mData.get(position));
}
public abstract int onHandleViewType(int position);
public abstract void onHandleViewHolder(VH holder, int position, T item);
@Override
public int getItemCount() {
return mData != null ? mData.size() : 0;
}
protected View getItemView(int layoutResId, ViewGroup parent) {
if (layoutResId != LAYOUT_NOT_FOUND) {
return mLayoutInflater.inflate(layoutResId, parent, false);
}
return null;
}
private int getLayoutId(int vieType) {
return mLayoutTypes.get(vieType, LAYOUT_NOT_FOUND);
}
protected VH createBaseViewHolder(View view) {
Class temp = getClass();
Class z = null;
while (z == null && null != temp) {
z = getInstancedGenericKClass(temp);
temp = temp.getSuperclass();
}
VH vh;
// 泛型擦除会导致 z 为 null
if (z == null) {
vh = (VH) new BaseFlowHolder(view);
} else {
vh = createGenericKInstance(z, view);
}
return vh != null ? vh : (VH) new BaseFlowHolder(view);
}
@SuppressWarnings("unchecked")
private VH createGenericKInstance(Class z, View view) {
try {
Constructor constructor;
// inner and unstatic class
if (z.isMemberClass() && !Modifier.isStatic(z.getModifiers())) {
constructor = z.getDeclaredConstructor(getClass(), View.class);
constructor.setAccessible(true);
return (VH) constructor.newInstance(this, view);
} else {
constructor = z.getDeclaredConstructor(View.class);
constructor.setAccessible(true);
return (VH) constructor.newInstance(view);
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
private Class getInstancedGenericKClass(Class z) {
Type type = z.getGenericSuperclass();
if (type instanceof ParameterizedType) {
Type[] types = ((ParameterizedType) type).getActualTypeArguments();
for (Type temp : types) {
if (temp instanceof Class) {
Class tempClass = (Class) temp;
if (BaseFlowHolder.class.isAssignableFrom(tempClass)) {
return tempClass;
}
} else if (temp instanceof ParameterizedType) {
Type rawType = ((ParameterizedType) temp).getRawType();
if (rawType instanceof Class && BaseFlowHolder.class.isAssignableFrom((Class<?>) rawType)) {
return (Class<?>) rawType;
}
}
}
}
return null;
}
}