T findViewById(@IdRes int resId) {
38 | if (itemView != null) {
39 | return (T) itemView.findViewById(resId);
40 | } else {
41 | return null;
42 | }
43 | }
44 |
45 | public void setData(final T data) {
46 | if (data == null) {
47 | return;
48 | }
49 | mData = data;
50 | }
51 |
52 | public T getData() {
53 | return mData;
54 | }
55 |
56 | public void onItemViewClick(T data) {
57 |
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/RefreshRecyclerView/src/main/java/cn/lemon/view/adapter/CustomMultiTypeAdapter.java:
--------------------------------------------------------------------------------
1 | package cn.lemon.view.adapter;
2 |
3 | import android.content.Context;
4 | import android.view.ViewGroup;
5 |
6 | import java.util.Arrays;
7 | import java.util.List;
8 |
9 | /**
10 | * 对应 ViewTypeManager
11 | *
12 | * Created by linlongxin on 2017/9/20.
13 | */
14 |
15 | public class CustomMultiTypeAdapter extends RecyclerAdapter {
16 |
17 | private final String TAG = "CustomMultiTypeAdapter";
18 | private ViewTypeManager mViewHolderManager;
19 |
20 |
21 | public CustomMultiTypeAdapter(Context context) {
22 | super(context);
23 | mViewHolderManager = new ViewTypeManager();
24 | }
25 |
26 | public void setViewHolderFactory(IViewHolderFactory factory) {
27 | if (factory == null) {
28 | throw new IllegalArgumentException("factory must not null");
29 | }
30 | mViewHolderManager.setViewHolderFactory(factory);
31 | }
32 |
33 | @Override
34 | public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
35 | if (viewType == STATUS_TYPE) {
36 | return new BaseViewHolder<>(mStatusView);
37 | } else {
38 | return mViewHolderManager.getViewHolder(parent, viewType);
39 | }
40 | }
41 |
42 | // 弃用
43 | @Override
44 | public BaseViewHolder onCreateBaseViewHolder(ViewGroup parent, int viewType) {
45 | return null;
46 | }
47 |
48 | @Override
49 | public void onBindViewHolder(BaseViewHolder holder, int position) {
50 | if (position < mData.size()) {
51 | holder.setData(mData.get(position));
52 | }
53 | // 显示加载更多
54 | if (!mIsNoMoring && mLoadMoreEnable && !mIsLoadMoring && isValidLoadMore(position)) {
55 | performLoadMore();
56 | }
57 | }
58 |
59 | @Override
60 | public int getItemViewType(int position) {
61 | if (hasEndStatusView() && position == mViewCount - 1) {
62 | return STATUS_TYPE;
63 | }
64 | return mViewHolderManager.getViewType(position);
65 | }
66 |
67 | public void add(int viewType) {
68 | add(new Object(), viewType);
69 | }
70 |
71 | public void add(T data, int viewType) {
72 | if (mIsNoMoring || data == null) {
73 | return;
74 | }
75 | mIsLoadMoring = false;
76 | mData.add(data);
77 | int positionStart;
78 | if (hasEndStatusView()) {
79 | positionStart = mViewCount - 1;
80 | } else {
81 | positionStart = mViewCount;
82 | }
83 | mViewHolderManager.putViewType(positionStart, viewType);
84 | mViewCount++;
85 | notifyItemRangeInserted(positionStart, 1);
86 | }
87 |
88 | public void addAll(T[] data, int viewType) {
89 | addAll(Arrays.asList(data), viewType);
90 | }
91 |
92 | public void addAll(List data, int viewType) {
93 |
94 | if (mIsNoMoring || data == null || data.size() == 0) {
95 | return;
96 | }
97 | mIsLoadMoring = false;
98 | int size = data.size();
99 | mData.addAll(data);
100 | int positionStart;
101 | if (hasEndStatusView()) {
102 | positionStart = mViewCount - 1;
103 | } else {
104 | positionStart = mViewCount;
105 | }
106 | for (int i = 0; i < size; i++) {
107 | mViewHolderManager.putViewType(positionStart + i, viewType);
108 | }
109 | mViewCount += size;
110 | notifyItemRangeInserted(positionStart, size);
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/RefreshRecyclerView/src/main/java/cn/lemon/view/adapter/IHandler.java:
--------------------------------------------------------------------------------
1 | package cn.lemon.view.adapter;
2 |
3 | import android.os.Message;
4 |
5 | /**
6 | * Created by linlongxin on 2018/3/29
7 | */
8 | public interface IHandler {
9 |
10 | void handMsg(Message message);
11 | }
12 |
--------------------------------------------------------------------------------
/RefreshRecyclerView/src/main/java/cn/lemon/view/adapter/IViewHolderFactory.java:
--------------------------------------------------------------------------------
1 | package cn.lemon.view.adapter;
2 |
3 | import android.view.ViewGroup;
4 |
5 | /**
6 | * 为避免反射,ViewType 交给开发者自己管理
7 | *
8 | * Created by linlongxin on 2017/9/20.
9 | */
10 |
11 | public interface IViewHolderFactory {
12 |
13 | V getViewHolder(ViewGroup parent, int viewType);
14 | }
15 |
--------------------------------------------------------------------------------
/RefreshRecyclerView/src/main/java/cn/lemon/view/adapter/MultiTypeAdapter.java:
--------------------------------------------------------------------------------
1 | package cn.lemon.view.adapter;
2 |
3 | import android.content.Context;
4 | import android.util.Log;
5 | import android.view.ViewGroup;
6 |
7 | import java.lang.reflect.Constructor;
8 | import java.util.Arrays;
9 | import java.util.List;
10 |
11 | /**
12 | * 复杂的数据类型列表 Adapter , 没有 Header , Footer 的概念,所有的 item 都对应一个 ViewHolder
13 | * 通过反射自动处理 onCreateViewHolder 过程,如需避免反射调用请使用 CustomMultiTypeAdapter
14 | *
15 | * Created by linlongxin on 2016/8/22.
16 | */
17 |
18 | public class MultiTypeAdapter extends RecyclerAdapter {
19 |
20 | private final String TAG = "MultiTypeAdapter";
21 | private ViewHolderManager mViewHolderManager;
22 |
23 | public MultiTypeAdapter(Context context) {
24 | super(context);
25 | mViewHolderManager = new ViewHolderManager();
26 | }
27 |
28 | @Override
29 | public int getItemViewType(int position) {
30 | if (hasEndStatusView() && position == mViewCount - 1) {
31 | return STATUS_TYPE;
32 | }
33 | return mViewHolderManager.getViewType(position);
34 | }
35 |
36 | @Override
37 | public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
38 | log("onCreateViewHolder -- viewType : " + viewType);
39 | if (mViewHolderManager == null) {
40 | throw new ExceptionInInitializerError("mViewHolderManager is null , it need init");
41 | }
42 | if (viewType == STATUS_TYPE) {
43 | return new BaseViewHolder(mStatusView);
44 | }
45 | Class clazzViewHolder = mViewHolderManager.getViewHolderClass(viewType);
46 | try {
47 | //这里只适配了 ViewHolder 构造函数只有 ViewGroup.class 参数 或者 无参 情况的构造函数,具体请看 Demo
48 | BaseViewHolder holder;
49 | Constructor constructor = clazzViewHolder.getDeclaredConstructor(new Class[]{ViewGroup.class});
50 | constructor.setAccessible(true);
51 | holder = (BaseViewHolder) constructor.newInstance(new Object[]{parent});
52 | if (holder == null) {
53 | constructor = clazzViewHolder.getDeclaredConstructor();
54 | holder = (BaseViewHolder) constructor.newInstance();
55 | }
56 | return holder;
57 | } catch (Exception e) {
58 | Log.e(TAG, "onCreateBaseViewHolder : " + e.getMessage());
59 | }
60 | return null;
61 | }
62 |
63 | @Override
64 | public BaseViewHolder onCreateBaseViewHolder(ViewGroup parent, int viewType) {
65 | return null;
66 | }
67 |
68 | @Override
69 | public void onBindViewHolder(BaseViewHolder holder, int position) {
70 | log("onBindViewHolder -- position : " + position);
71 | if (position < mData.size()){
72 | holder.setData(mData.get(position));
73 | }
74 | // 显示加载更多
75 | if (!mIsNoMoring && mLoadMoreEnable && !mIsLoadMoring && isValidLoadMore(position)) {
76 | performLoadMore();
77 | }
78 | }
79 |
80 | public void add(Class extends BaseViewHolder> viewHolder, T data) {
81 | if (mIsNoMoring || data == null || viewHolder == null) {
82 | return;
83 | }
84 | mIsLoadMoring = false;
85 | mData.add(data);
86 | mViewHolderManager.addViewHolder(viewHolder);
87 | int viewType = mViewHolderManager.getViewType(viewHolder);
88 |
89 | int positionStart;
90 |
91 | if (hasEndStatusView()) {
92 | positionStart = mViewCount - 1;
93 | } else {
94 | positionStart = mViewCount;
95 | }
96 | if (positionStart >= 0) {
97 | mViewHolderManager.putViewType(positionStart, viewType);
98 | mViewCount++;
99 | notifyItemRangeInserted(positionStart, 1);
100 | }
101 | }
102 |
103 | public void addAll(Class extends BaseViewHolder> viewHolder, T[] data) {
104 | addAll(viewHolder, Arrays.asList(data));
105 | }
106 |
107 | public void addAll(Class extends BaseViewHolder> viewHolder, List data) {
108 | if (mIsNoMoring || data == null || data.size() == 0) {
109 | return;
110 | }
111 | mIsLoadMoring = false;
112 | int size = data.size();
113 | mData.addAll(data);
114 | mViewHolderManager.addViewHolder(viewHolder);
115 | int viewType = mViewHolderManager.getViewType(viewHolder);
116 |
117 | int positionStart;
118 | if (hasEndStatusView()) {
119 | positionStart = mViewCount - 1;
120 | } else {
121 | positionStart = mViewCount;
122 | }
123 | if (positionStart >= 0) {
124 | for (int i = 0; i < size; i++) {
125 | mViewHolderManager.putViewType(positionStart + i, viewType);
126 | }
127 | mViewCount += size;
128 | notifyItemRangeInserted(positionStart, size);
129 | }
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/RefreshRecyclerView/src/main/java/cn/lemon/view/adapter/RecyclerAdapter.java:
--------------------------------------------------------------------------------
1 | package cn.lemon.view.adapter;
2 |
3 | import android.content.Context;
4 | import android.os.Message;
5 | import android.support.annotation.LayoutRes;
6 | import android.support.v7.widget.RecyclerView;
7 | import android.util.Log;
8 | import android.view.LayoutInflater;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 | import android.widget.FrameLayout;
12 | import android.widget.TextView;
13 | import android.widget.Toast;
14 |
15 | import java.util.ArrayList;
16 | import java.util.Arrays;
17 | import java.util.List;
18 |
19 | import cn.lemon.view.R;
20 | import cn.lemon.view.util.LogUtils;
21 |
22 |
23 | /**
24 | * Created by linlongxin on 2015/12/19.
25 | */
26 | public abstract class RecyclerAdapter extends RecyclerView.Adapter> implements IHandler {
27 |
28 | private static final String TAG = RecyclerAdapter.class.getSimpleName();
29 |
30 | private static final int MSG_SHOW_NO_MORE = 1 << 1;
31 | private static final int MSG_SHOW_LOAD_MORE = 1 << 2;
32 | private static final int MSG_SHOW_LOAD_MORE_ERROR = 1 << 3;
33 |
34 | public static final int HEADER_TYPE = 111;
35 | public static final int FOOTER_TYPE = 222;
36 | public static final int STATUS_TYPE = 333;
37 |
38 | protected int mViewCount = 0;
39 |
40 | private boolean hasHeader = false;
41 | private boolean hasFooter = false;
42 | // 是否可加载更多
43 | protected boolean mLoadMoreEnable = false;
44 | // 是否可显示 no more
45 | protected boolean mNoMoreEnable = false;
46 | // 是否正在显示 load more
47 | protected boolean mIsLoadMoring = false;
48 | // 是否正在显示 no more
49 | protected boolean mIsNoMoring = false;
50 |
51 | protected List mLoadMoreActions = new ArrayList<>();
52 | protected List mErrorActions = new ArrayList<>();
53 |
54 | protected List mData = new ArrayList<>();
55 |
56 | private View headerView;
57 | private View footerView;
58 | private View mLoadMoreLayout;
59 | private View mLoadMoreView;
60 | private TextView mLoadMoreError;
61 | private TextView mNoMoreView;
62 | protected View mStatusView;
63 |
64 | private Context mContext;
65 |
66 | private WeakHandler mHandler = new WeakHandler(this);
67 |
68 | public RecyclerAdapter(Context context) {
69 | mContext = context;
70 | }
71 |
72 | public RecyclerAdapter(Context context, T[] data) {
73 | this(context, Arrays.asList(data));
74 | }
75 |
76 | public RecyclerAdapter(Context context, List data) {
77 | mContext = context;
78 | this.mData = data;
79 | mViewCount += data.size();
80 | notifyDataSetChanged();
81 | }
82 |
83 | private void initEndStatusView() {
84 | if (hasEndStatusView() && mStatusView == null) {
85 | mStatusView = LayoutInflater.from(getContext()).inflate(R.layout.view_status_last, null);
86 | mStatusView.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
87 | mLoadMoreLayout = mStatusView.findViewById(R.id.load_more_Layout);
88 | mLoadMoreView = mStatusView.findViewById(R.id.load_more_loading);
89 | mLoadMoreError = (TextView) mStatusView.findViewById(R.id.load_more_error);
90 | mNoMoreView = (TextView) mStatusView.findViewById(R.id.no_more_view);
91 | mViewCount++;
92 | mLoadMoreError.setOnClickListener(new View.OnClickListener() {
93 | @Override
94 | public void onClick(View v) {
95 | mHandler.sendEmptyMessage(MSG_SHOW_LOAD_MORE);
96 | for (Action action : mErrorActions) {
97 | action.onAction();
98 | }
99 | }
100 | });
101 | }
102 | }
103 |
104 | public void setLoadMoreEnable(boolean b) {
105 | mLoadMoreEnable = b;
106 | initEndStatusView();
107 | }
108 |
109 | public void setShowNoMoreEnable(boolean b) {
110 | mNoMoreEnable = b;
111 | initEndStatusView();
112 | }
113 |
114 | public boolean isShowNoMoring() {
115 | return mIsNoMoring;
116 | }
117 |
118 | @Override
119 | public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
120 | if (viewType == HEADER_TYPE) {
121 | return new BaseViewHolder<>(headerView);
122 | } else if (viewType == FOOTER_TYPE) {
123 | return new BaseViewHolder<>(footerView);
124 | } else if (viewType == STATUS_TYPE) {
125 | return new BaseViewHolder<>(mStatusView);
126 | } else {
127 | return onCreateBaseViewHolder(parent, viewType);
128 | }
129 | }
130 |
131 | public abstract BaseViewHolder onCreateBaseViewHolder(ViewGroup parent, int viewType);
132 |
133 | @Override
134 | public void onBindViewHolder(BaseViewHolder holder, int position) {
135 | log("onBindViewHolder() viewCount : " + mViewCount + " position : " + position);
136 | if (holder == null || position < 0) {
137 | return;
138 | }
139 | int dataSize = mData.size();
140 | if (hasEndStatusView()) {
141 | if (!hasHeader && !hasFooter && position < dataSize) {
142 | //没有Header和Footer
143 | holder.setData(mData.get(position));
144 | } else if (hasHeader && !hasFooter && position > 0 && position < mViewCount - 1 && position - 1 < dataSize) {
145 | //有Header没有Footer
146 | holder.setData(mData.get(position - 1));
147 | } else if (!hasHeader && position < mViewCount - 2 && position < dataSize) {
148 | //没有Header,有Footer
149 | holder.setData(mData.get(position));
150 | } else if (position > 0 && position < mViewCount - 2 && position - 1 < dataSize) {
151 | //Header, Footer 都有
152 | holder.setData(mData.get(position - 1));
153 | }
154 | } else {
155 | if (!hasHeader && !hasFooter && position < dataSize) {
156 | //没有Header和Footer
157 | holder.setData(mData.get(position));
158 | } else if (hasHeader && !hasFooter && position > 0 && position < mViewCount && position - 1 < dataSize) {
159 | //有Header没有Footer
160 | holder.setData(mData.get(position - 1));
161 | } else if (!hasHeader && position < mViewCount - 1 && position < dataSize) {
162 | //没有Header,有Footer
163 | holder.setData(mData.get(position));
164 | } else if (position > 0 && position < mViewCount - 1 && position - 1 < dataSize) {
165 | //Header, Footer 都有
166 | holder.setData(mData.get(position - 1));
167 | }
168 | }
169 |
170 | // 最后一个可见的 item 时 加载更多。解决 remove 时 bug
171 | if (mLoadMoreEnable && !mIsNoMoring && !mIsLoadMoring && isValidLoadMore(position)) {
172 | performLoadMore();
173 | }
174 | }
175 |
176 | protected void performLoadMore(){
177 | log("load more");
178 | mIsLoadMoring = true;
179 | setViewVisible(mLoadMoreLayout, true);
180 | setViewVisible(mLoadMoreView, true);
181 | setViewVisible(mLoadMoreError, false);
182 | setViewVisible(mNoMoreView, false);
183 | for (Action action : mLoadMoreActions) {
184 | action.onAction();
185 | }
186 | }
187 |
188 | /**
189 | * load more 当前位置 view 是否有效
190 | */
191 | protected boolean isValidLoadMore(int position) {
192 | if (hasEndStatusView()) {
193 | // 倒数第二个 item 就load more ,提前触发。(解决一些极端 case 导致 bug 并提前加载数据,提高加载效率)
194 | if (hasHeader) {
195 | return position > 1 && position == mViewCount - 3 && mViewCount != 2;
196 | } else {
197 | return position > 0 && position == mViewCount - 2 && mViewCount != 1;
198 | }
199 | } else {
200 | return false;
201 | }
202 | }
203 |
204 | /**
205 | * ViewHolder 根据 Item 的位置选择 ViewType
206 | */
207 | @Override
208 | public int getItemViewType(int position) {
209 | // header
210 | if (hasHeader && position == 0) {
211 | return HEADER_TYPE;
212 | }
213 | // footer
214 | if (hasFooter && hasEndStatusView() && position == mViewCount - 2) {
215 | return FOOTER_TYPE;
216 | } else if (hasFooter && !hasEndStatusView() && position == mViewCount - 1) {
217 | return FOOTER_TYPE;
218 | }
219 | // status
220 | if (hasEndStatusView() && position == mViewCount - 1) {
221 | return STATUS_TYPE;
222 | }
223 |
224 | return super.getItemViewType(position);
225 | }
226 |
227 | /**
228 | * 包含了 Header , Footer , 状态显示 Item
229 | */
230 | @Override
231 | public int getItemCount() {
232 | return mViewCount;
233 | }
234 |
235 | public void showNoMore() {
236 | if (!mNoMoreEnable) {
237 | return;
238 | }
239 | mIsNoMoring = true;
240 | mHandler.sendEmptyMessage(MSG_SHOW_NO_MORE);
241 | }
242 |
243 | public void showLoadMoreError() {
244 | if (!mLoadMoreEnable) {
245 | return;
246 | }
247 | mHandler.sendEmptyMessage(MSG_SHOW_LOAD_MORE_ERROR);
248 | }
249 |
250 | public void addLoadMoreErrorAction(Action action) {
251 | if (action == null){
252 | return;
253 | }
254 | mErrorActions.add(action);
255 | }
256 |
257 | public void openLoadMore() {
258 | mIsNoMoring = false;
259 | mHandler.sendEmptyMessage(MSG_SHOW_LOAD_MORE);
260 | }
261 |
262 | public void addLoadMoreAction(Action action) {
263 | if (action == null){
264 | return;
265 | }
266 | mLoadMoreActions.add(action);
267 | }
268 |
269 | public void add(T object) {
270 | if (!mIsNoMoring && object != null) {
271 | mIsLoadMoring = false;
272 | mData.add(object);
273 | int position;
274 | if (hasFooter && hasEndStatusView()) {
275 | position = mViewCount - 2;
276 | } else if (hasFooter && !hasEndStatusView()) {
277 | position = mViewCount - 1;
278 | } else if (!hasFooter && hasEndStatusView()) {
279 | position = mViewCount - 1;
280 | } else {
281 | position = mViewCount;
282 | }
283 | mViewCount++;
284 | notifyItemInserted(position);
285 | }
286 | }
287 |
288 | public void insert(T object, int itemPosition) {
289 | int maxPosition = hasEndStatusView() ? mViewCount - 2 : mViewCount - 1;
290 | if (mData != null && itemPosition < maxPosition && object != null) {
291 | int dataPosition;
292 | if (hasHeader) {
293 | dataPosition = itemPosition - 1;
294 | } else {
295 | dataPosition = itemPosition;
296 | }
297 | mData.add(dataPosition, object);
298 | mViewCount++;
299 | notifyItemInserted(itemPosition);
300 | }
301 | }
302 |
303 | public void addAll(List data) {
304 | if (data == null) {
305 | return;
306 | }
307 | int size = data.size();
308 | if (!mIsNoMoring && size > 0) {
309 | mIsLoadMoring = false;
310 | mData.addAll(data);
311 | int positionStart;
312 | if (hasFooter && hasEndStatusView()) {
313 | positionStart = mViewCount - 2;
314 | } else if (hasFooter && !hasEndStatusView()) {
315 | positionStart = mViewCount - 1;
316 | } else if (!hasFooter && hasEndStatusView()) {
317 | positionStart = mViewCount - 1;
318 | } else {
319 | positionStart = mViewCount;
320 | }
321 | mViewCount += size;
322 | notifyItemRangeInserted(positionStart, size);
323 | log("addAll() startPosition : " + positionStart + " itemCount : " + size);
324 | }
325 | }
326 |
327 | public void addAll(T[] objects) {
328 | addAll(Arrays.asList(objects));
329 | }
330 |
331 | public void replace(T object, int itemPosition) {
332 | if (mData != null && object != null) {
333 | int dataPosition;
334 | if (hasHeader) {
335 | dataPosition = itemPosition - 1;
336 | } else {
337 | dataPosition = itemPosition;
338 | }
339 | if (dataPosition < mData.size()) {
340 | mData.set(dataPosition, object);
341 | mViewCount++;
342 | notifyItemChanged(itemPosition);
343 | }
344 | }
345 | }
346 |
347 | //position start with 0
348 | public void remove(T object) {
349 | if (object != null && !mData.contains(object)) {
350 | log("without the object : " + object.getClass().getName());
351 | return;
352 | }
353 | int dataPosition = mData.indexOf(object);
354 | int itemPosition;
355 | if (hasHeader) {
356 | itemPosition = dataPosition + 1;
357 | } else {
358 | itemPosition = dataPosition;
359 | }
360 | remove(itemPosition);
361 | }
362 |
363 | /**
364 | * positionItem start with 0
365 | */
366 | public void remove(int itemPosition) {
367 | int dataPosition;
368 | int dataSize = mData.size();
369 | if (hasHeader) {
370 | dataPosition = itemPosition - 1;
371 | if (dataPosition >= 0 && dataPosition < dataSize) {
372 | mData.remove(dataPosition);
373 | notifyItemRemoved(itemPosition);
374 | mViewCount--;
375 | } else if (dataPosition >= dataSize) {
376 | throw new IllegalArgumentException("itemPosition is greater than data size");
377 | } else {
378 | throw new IndexOutOfBoundsException("RecyclerView has header,position is should more than 0 ." +
379 | "if you want remove header , pleasure user removeHeader()");
380 | }
381 | } else {
382 | dataPosition = itemPosition;
383 | if (dataPosition >= dataSize) {
384 | throw new IllegalArgumentException("itemPosition is greater than data size");
385 | } else {
386 | mData.remove(dataPosition);
387 | notifyItemRemoved(itemPosition);
388 | mViewCount--;
389 | }
390 | }
391 | }
392 |
393 | public void clear() {
394 | mData.clear();
395 | mViewCount = hasEndStatusView() ? 1 : 0;
396 | if (hasHeader) {
397 | mViewCount++;
398 | }
399 | if (hasFooter) {
400 | mViewCount++;
401 | }
402 | mIsNoMoring = false;
403 | mIsLoadMoring = false;
404 | setViewVisible(mLoadMoreLayout, false);
405 | setViewVisible(mNoMoreView, false);
406 | notifyDataSetChanged();
407 | }
408 |
409 | /**
410 | * header 不负责数据加载,不会调用 onBindViewHolder
411 | */
412 | public void setHeader(View header) {
413 | hasHeader = true;
414 | headerView = header;
415 | mViewCount++;
416 | }
417 |
418 | public void setHeader(@LayoutRes int res) {
419 | setHeader(LayoutInflater.from(mContext).inflate(res, null));
420 | }
421 |
422 | public View getHeader() {
423 | return headerView;
424 | }
425 |
426 | public View getFooter() {
427 | return footerView;
428 | }
429 |
430 | public void setFooter(View footer) {
431 | hasFooter = true;
432 | footerView = footer;
433 | mViewCount++;
434 | }
435 |
436 | /**
437 | * Footer 这里不负责数据的加载
438 | *
439 | * @param res
440 | */
441 | public void setFooter(@LayoutRes int res) {
442 | setFooter(LayoutInflater.from(mContext).inflate(res, null));
443 | }
444 |
445 | public void removeHeader() {
446 | if (hasHeader) {
447 | hasHeader = false;
448 | notifyItemRemoved(0);
449 | }
450 | }
451 |
452 | public void removeFooter() {
453 | if (hasFooter) {
454 | hasFooter = false;
455 | if (hasEndStatusView() && mViewCount > 1) {
456 | notifyItemRemoved(mViewCount - 2);
457 | } else if (!hasEndStatusView() && mViewCount > 0) {
458 | notifyItemRemoved(mViewCount - 1);
459 | }
460 | }
461 | }
462 |
463 | public List getData() {
464 | return mData;
465 | }
466 |
467 | public Context getContext() {
468 | return mContext;
469 | }
470 |
471 | protected void setViewVisible(View view, boolean visibile) {
472 | if (view != null) {
473 | view.setVisibility(visibile ? View.VISIBLE : View.GONE);
474 | }
475 | }
476 |
477 | protected boolean hasEndStatusView() {
478 | return mLoadMoreEnable || mNoMoreEnable;
479 | }
480 |
481 | @Override
482 | public void handMsg(Message message) {
483 | switch (message.what) {
484 | case MSG_SHOW_LOAD_MORE_ERROR:
485 | // true 阻止 load more 执行
486 | mIsLoadMoring = true;
487 | setViewVisible(mLoadMoreLayout, true);
488 | setViewVisible(mLoadMoreView, false);
489 | setViewVisible(mLoadMoreError, true);
490 | setViewVisible(mNoMoreView, false);
491 | break;
492 | case MSG_SHOW_LOAD_MORE:
493 | mIsLoadMoring = true;
494 | setViewVisible(mLoadMoreLayout, true);
495 | setViewVisible(mLoadMoreView, true);
496 | setViewVisible(mLoadMoreError, false);
497 | setViewVisible(mNoMoreView, false);
498 | break;
499 | case MSG_SHOW_NO_MORE:
500 | mIsLoadMoring = false;
501 | setViewVisible(mLoadMoreLayout, false);
502 | setViewVisible(mNoMoreView, true);
503 | break;
504 | default:
505 | break;
506 | }
507 | }
508 |
509 | protected void log(String content) {
510 | LogUtils.log(TAG, content);
511 | }
512 | }
513 |
--------------------------------------------------------------------------------
/RefreshRecyclerView/src/main/java/cn/lemon/view/adapter/ViewHolderManager.java:
--------------------------------------------------------------------------------
1 | package cn.lemon.view.adapter;
2 |
3 | import android.util.Log;
4 | import android.util.SparseArray;
5 | import android.util.SparseIntArray;
6 |
7 | import java.lang.reflect.ParameterizedType;
8 | import java.util.HashMap;
9 | import java.util.Map;
10 |
11 | /**
12 | * Created by linlongxin on 2016/8/22.
13 | */
14 |
15 | public class ViewHolderManager {
16 |
17 | private final String TAG = "ViewHolderManager";
18 | private int mViewType = 10;
19 | private Map, Integer> mHolderToTypeMap;
20 | private SparseArray> mTypeToHolderMap;
21 | //position to ViewType
22 | private SparseIntArray mPositionToTypeMap;
23 |
24 | public ViewHolderManager() {
25 | mHolderToTypeMap = new HashMap<>();
26 | mTypeToHolderMap = new SparseArray<>();
27 | mPositionToTypeMap = new SparseIntArray();
28 | }
29 |
30 | public void putViewType(int position, int type){
31 | mPositionToTypeMap.put(position, type);
32 | }
33 |
34 | public int getViewType(int position) {
35 | return mPositionToTypeMap.get(position);
36 | }
37 |
38 | public void addViewHolder(Class extends BaseViewHolder> viewHolder) {
39 | if (!mHolderToTypeMap.containsKey(viewHolder)) {
40 | //获取ViewHolder的泛型数据class
41 | Class dataClass = (Class) ((ParameterizedType) viewHolder.getGenericSuperclass()).getActualTypeArguments()[0];
42 | mViewType ++;
43 | mHolderToTypeMap.put(viewHolder, mViewType);
44 | mTypeToHolderMap.put(mViewType,viewHolder);
45 | Log.d(TAG, "addViewHolder dataClassType : " + dataClass.getName());
46 | }
47 | }
48 |
49 | public int getViewType(Class extends BaseViewHolder> holder){
50 | if(!mHolderToTypeMap.containsKey(holder)){
51 | throw new IllegalArgumentException("please invoke add ViewHolder method");
52 | }
53 | return mHolderToTypeMap.get(holder);
54 | }
55 |
56 | public Class extends BaseViewHolder> getViewHolderClass(int viewType){
57 | if(mTypeToHolderMap.get(viewType) == null){
58 | throw new IllegalArgumentException("please invoke add ViewHolder method");
59 | }
60 | return mTypeToHolderMap.get(viewType);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/RefreshRecyclerView/src/main/java/cn/lemon/view/adapter/ViewTypeManager.java:
--------------------------------------------------------------------------------
1 | package cn.lemon.view.adapter;
2 |
3 | import android.util.SparseIntArray;
4 | import android.view.ViewGroup;
5 |
6 | /**
7 | * 为避免反射,ViewType 交给开发者自己管理(IViewTypeFactory)
8 | *
9 | * Created by linlongxin on 2017/9/20.
10 | */
11 |
12 | public class ViewTypeManager {
13 |
14 | private final String TAG = "ViewTypeManager";
15 | // position to Type
16 | private SparseIntArray mPositionToTypeMap;
17 |
18 | private IViewHolderFactory mViewHolderFactory;
19 |
20 | public ViewTypeManager() {
21 | mPositionToTypeMap = new SparseIntArray();
22 | }
23 |
24 | protected int getViewType(int position) {
25 | return mPositionToTypeMap.get(position);
26 | }
27 |
28 | protected void putViewType(int position, int viewType) {
29 | mPositionToTypeMap.put(position, viewType);
30 | }
31 |
32 | public void setViewHolderFactory(IViewHolderFactory factory){
33 | mViewHolderFactory = factory;
34 | }
35 |
36 | protected T getViewHolder(ViewGroup parent, int viewType){
37 | if (mViewHolderFactory != null) {
38 | return mViewHolderFactory.getViewHolder(parent, viewType);
39 | } else {
40 | return null;
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/RefreshRecyclerView/src/main/java/cn/lemon/view/adapter/WeakHandler.java:
--------------------------------------------------------------------------------
1 | package cn.lemon.view.adapter;
2 |
3 | import android.os.Handler;
4 | import android.os.Message;
5 | import java.lang.ref.WeakReference;
6 |
7 | /**
8 | * Created by linlongxin on 2018/3/29
9 | */
10 | public class WeakHandler extends Handler {
11 |
12 | private WeakReference mHandler;
13 |
14 | public WeakHandler(IHandler handler) {
15 | this.mHandler = new WeakReference<>(handler);
16 | }
17 |
18 | @Override
19 | public void handleMessage(Message msg) {
20 | super.handleMessage(msg);
21 | IHandler handler = mHandler.get();
22 | if (handler != null) {
23 | handler.handMsg(msg);
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/RefreshRecyclerView/src/main/java/cn/lemon/view/util/LogUtils.java:
--------------------------------------------------------------------------------
1 | package cn.lemon.view.util;
2 |
3 | import android.util.Log;
4 |
5 | /**
6 | * Created by linlongxin on 2018/8/9
7 | */
8 | public class LogUtils {
9 |
10 | private static boolean DEBUG = false;
11 |
12 | public static void setLogEnale(boolean b){
13 | DEBUG = b;
14 | }
15 |
16 | public static void log(String tag, String content) {
17 | if (DEBUG) {
18 | Log.i(tag, content);
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/RefreshRecyclerView/src/main/res/drawable/bg_button_retry_adapter.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/RefreshRecyclerView/src/main/res/layout/view_refresh_recycler.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
13 |
14 |
--------------------------------------------------------------------------------
/RefreshRecyclerView/src/main/res/layout/view_status_last.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
15 |
16 |
20 |
21 |
24 |
25 |
31 |
32 |
33 |
34 |
42 |
43 |
44 |
45 |
53 |
54 |
--------------------------------------------------------------------------------
/RefreshRecyclerView/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | google()
7 | }
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.1.3'
10 | classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.0'
11 | classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0'
12 | // NOTE: Do not place your application dependencies here; they belong
13 | // in the individual module build.gradle files
14 | }
15 | }
16 |
17 | allprojects {
18 | repositories {
19 | jcenter()
20 | google()
21 | }
22 | }
23 |
24 | task clean(type: Delete) {
25 | delete rootProject.buildDir
26 | }
27 |
--------------------------------------------------------------------------------
/demo/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/demo/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | mavenCentral()
4 | jcenter()
5 | }
6 | dependencies {
7 | classpath 'com.lemon:code-lines-plugin:1.3'
8 | }
9 | }
10 |
11 | apply plugin: 'com.android.application'
12 | apply plugin: 'code-lines'
13 |
14 | android {
15 | compileSdkVersion 25
16 | buildToolsVersion '27.0.3'
17 |
18 | defaultConfig {
19 | applicationId "cn.lemon.recyclerview"
20 | minSdkVersion 15
21 | targetSdkVersion 25
22 | versionCode 1
23 | versionName "1.0"
24 | multiDexEnabled true
25 | }
26 | buildTypes {
27 | release {
28 | minifyEnabled false
29 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
30 | }
31 | }
32 | compileOptions {
33 | sourceCompatibility JavaVersion.VERSION_1_8
34 | targetCompatibility JavaVersion.VERSION_1_8
35 | }
36 | }
37 |
38 | codeLinesExtension {
39 | dir = 'demo/src' // 统计的路径
40 | suffixs = ['.java', '.xml'] // 统计的文件类型
41 | }
42 |
43 | dependencies {
44 | //noinspection GradleCompatible
45 | implementation 'com.android.support:appcompat-v7:25.4.0'
46 | implementation 'com.android.support:design:25.4.0'
47 | implementation 'cn.alien95:util:1.1.3'
48 | implementation 'com.github.bumptech.glide:glide:3.7.0'
49 | implementation 'com.android.support:cardview-v7:25.4.0'
50 | implementation project(':RefreshRecyclerView')
51 | implementation 'com.android.support.constraint:constraint-layout:1.0.2'
52 | }
53 |
--------------------------------------------------------------------------------
/demo/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in F:\SoftWare\android-sdk-windows/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/demo/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
15 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
27 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/demo/src/main/java/cn/lemon/recyclerview/app/App.java:
--------------------------------------------------------------------------------
1 | package cn.lemon.recyclerview.app;
2 |
3 | import android.app.Application;
4 |
5 | import cn.alien95.util.Utils;
6 |
7 |
8 | /**
9 | * Created by linlongxin on 2016/1/24.
10 | */
11 | public class App extends Application {
12 |
13 | @Override
14 | public void onCreate() {
15 | super.onCreate();
16 |
17 | Utils.initialize(this);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/demo/src/main/java/cn/lemon/recyclerview/ui/CardRecordAdapter.java:
--------------------------------------------------------------------------------
1 | package cn.lemon.recyclerview.ui;
2 |
3 | import android.content.Context;
4 | import android.view.ViewGroup;
5 |
6 | import cn.lemon.recyclerview.ui.bean.Consumption;
7 | import cn.lemon.view.adapter.BaseViewHolder;
8 | import cn.lemon.view.adapter.RecyclerAdapter;
9 |
10 |
11 | class CardRecordAdapter extends RecyclerAdapter {
12 |
13 | public CardRecordAdapter(Context context) {
14 | super(context);
15 | }
16 |
17 | @Override
18 | public BaseViewHolder onCreateBaseViewHolder(ViewGroup parent, int viewType) {
19 | return new CardRecordHolder(parent);
20 | }
21 | }
--------------------------------------------------------------------------------
/demo/src/main/java/cn/lemon/recyclerview/ui/CardRecordHolder.java:
--------------------------------------------------------------------------------
1 | package cn.lemon.recyclerview.ui;
2 |
3 | import android.util.Log;
4 | import android.view.ViewGroup;
5 | import android.widget.TextView;
6 |
7 | import cn.lemon.recyclerview.R;
8 | import cn.lemon.recyclerview.ui.bean.Consumption;
9 | import cn.lemon.view.adapter.BaseViewHolder;
10 |
11 | class CardRecordHolder extends BaseViewHolder {
12 |
13 | private TextView name;
14 | private TextView type;
15 | private TextView consumeNum;
16 | private TextView remainNum;
17 | private TextView consumeAddress;
18 | private TextView time;
19 |
20 | public CardRecordHolder(ViewGroup parent) {
21 | super(parent, R.layout.holder_consume);
22 | }
23 |
24 | @Override
25 | public void setData(final Consumption object) {
26 | super.setData(object);
27 | name.setText("Demo");
28 | type.setText(object.getLx());
29 | consumeNum.setText("消费金额:" + object.getJe());
30 | remainNum.setText("卡里余额:" + object.getYe());
31 | consumeAddress.setText(object.getSh());
32 | time.setText(object.getSj());
33 | }
34 |
35 | @Override
36 | public void onInitializeView() {
37 | super.onInitializeView();
38 | name = findViewById(R.id.name);
39 | type = findViewById(R.id.type);
40 | consumeNum = findViewById(R.id.consume_num);
41 | remainNum = findViewById(R.id.remain_num);
42 | consumeAddress = findViewById(R.id.consume_address);
43 | time = findViewById(R.id.time);
44 | }
45 |
46 | @Override
47 | public void onItemViewClick(Consumption object) {
48 | super.onItemViewClick(object);
49 | //点击事件
50 | Log.i("CardRecordHolder","onItemViewClick");
51 | }
52 | }
--------------------------------------------------------------------------------
/demo/src/main/java/cn/lemon/recyclerview/ui/CustomMultiTypeActivity.java:
--------------------------------------------------------------------------------
1 | package cn.lemon.recyclerview.ui;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.support.design.widget.FloatingActionButton;
6 | import android.support.v7.app.AppCompatActivity;
7 | import android.support.v7.widget.LinearLayoutManager;
8 | import android.support.v7.widget.Toolbar;
9 | import android.view.Menu;
10 | import android.view.MenuItem;
11 | import android.view.View;
12 | import android.view.ViewGroup;
13 |
14 | import cn.lemon.recyclerview.R;
15 | import cn.lemon.recyclerview.ui.bean.Consumption;
16 | import cn.lemon.recyclerview.ui.bean.TextImage;
17 | import cn.lemon.view.RefreshRecyclerView;
18 | import cn.lemon.view.adapter.Action;
19 | import cn.lemon.view.adapter.BaseViewHolder;
20 | import cn.lemon.view.adapter.CustomMultiTypeAdapter;
21 | import cn.lemon.view.adapter.IViewHolderFactory;
22 |
23 | public class CustomMultiTypeActivity extends AppCompatActivity implements IViewHolderFactory{
24 |
25 | private RefreshRecyclerView mRecyclerView;
26 | private CustomMultiTypeAdapter mAdapter;
27 | private int mPage = 0;
28 |
29 | @Override
30 | protected void onCreate(Bundle savedInstanceState) {
31 | super.onCreate(savedInstanceState);
32 | setContentView(R.layout.activity_custom_multi_type);
33 |
34 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
35 | setSupportActionBar(toolbar);
36 |
37 | mRecyclerView = (RefreshRecyclerView) findViewById(R.id.recycler_view);
38 | mRecyclerView.setSwipeRefreshColors(0xFF437845,0xFFE44F98,0xFF2FAC21);
39 | mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
40 | mAdapter = new CustomMultiTypeAdapter(this);
41 | mAdapter.setViewHolderFactory(this);
42 | mRecyclerView.setAdapter(mAdapter);
43 | mRecyclerView.addRefreshAction(() -> getData(true));
44 | mRecyclerView.addLoadMoreAction(() -> getData(false));
45 | mRecyclerView.post(() -> {
46 | mRecyclerView.showSwipeRefresh();
47 | getData(true);
48 | });
49 | mRecyclerView.addLoadMoreErrorAction(() -> getData(false));
50 |
51 | FloatingActionButton mFab = (FloatingActionButton) findViewById(R.id.fab);
52 | mFab.setOnClickListener(v -> mAdapter.add(getImageVirtualData(), VIEW_TYPE_IAMGE));
53 | }
54 |
55 | public void getData(final boolean isRefresh) {
56 | if (isRefresh) {
57 | mPage = 1;
58 | } else {
59 | mPage++;
60 | }
61 | if (mPage == 3) {
62 | mAdapter.showLoadMoreError();
63 | return;
64 | }
65 | mRecyclerView.postDelayed(new Runnable() {
66 | @Override
67 | public void run() {
68 | if (isRefresh) {
69 | mAdapter.clear();
70 | mRecyclerView.dismissSwipeRefresh();
71 | }
72 | mAdapter.add(getImageVirtualData(), VIEW_TYPE_IAMGE);
73 | mAdapter.addAll(getTextVirtualData(), VIEW_TYPE_TEXT);
74 | mAdapter.addAll(getTextImageVirualData(), VIEW_TYPE_TEXT_IMAGE);
75 | mAdapter.addAll(getRecordVirtualData(), VIEW_TYPE_CARD);
76 | if (mPage >= 5) {
77 | mAdapter.showNoMore();
78 | }
79 | if(isRefresh){
80 | mRecyclerView.getRecyclerView().scrollToPosition(0);
81 | }
82 | }
83 | }, 1000);
84 | }
85 |
86 | public String getImageVirtualData() {
87 | return "http://i03.pictn.sogoucdn.com/3c28af542f2d49f7-fe9c78d2ff4ac332-73d7732e20e2fcfaa954979d623bcbe9_qq";
88 | }
89 |
90 | public String[] getTextVirtualData() {
91 | return new String[]{
92 | "算机相关知识科普博客还有他",
93 | "技术职级规律越来越摸"
94 | };
95 | }
96 |
97 | public TextImage[] getTextImageVirualData() {
98 | return new TextImage[]{
99 | new TextImage("http://i03.pictn.sogoucdn.com/3c28af542f2d49f7-9e7c5d699eaea93e-3f7e1bcc57cbe10e050bf58559b0d5ae_qq", "小猫咪"),
100 | new TextImage("http://i03.pictn.sogoucdn.com/3c28af542f2d49f7-8f0182a4cf50287e-ba43c5aef499c64e6a3297c5c500c7dc_qq", "那些年,我还是帅哥"),
101 | new TextImage("http://img02.sogoucdn.com/app/a/100520093/803d8006b5d521bb-2eb356b9e8bc4ae6-0725fb0ad48d8b3a32f08eb150380bba.jpg", "看片。。。")
102 | };
103 | }
104 |
105 | public Consumption[] getRecordVirtualData() {
106 | return new Consumption[]{
107 | new Consumption("Demo", "2015-12-18 12:09", "消费", 9.7f, 24.19f, "兴业源三楼"),
108 | new Consumption("Demo", "2015-12-18 12:09", "消费", 9.7f, 24.19f, "兴业源三楼"),
109 | new Consumption("Demo", "2015-12-18 12:09", "消费", 9.7f, 24.19f, "兴业源三楼"),
110 | new Consumption("Demo", "2015-12-18 12:09", "消费", 9.7f, 24.19f, "兴业源三楼")
111 | };
112 | }
113 |
114 | private final int VIEW_TYPE_TEXT = 128 << 1;
115 | private final int VIEW_TYPE_IAMGE = 128 << 2;
116 | private final int VIEW_TYPE_TEXT_IMAGE = 128 << 3;
117 | private final int VIEW_TYPE_CARD = 128<<4;
118 |
119 | @Override
120 | public V getViewHolder(ViewGroup parent, int viewType) {
121 | switch (viewType) {
122 | case VIEW_TYPE_TEXT:
123 | return (V) new TextViewHolder(parent);
124 | case VIEW_TYPE_IAMGE:
125 | return (V) new ImageViewHolder(parent);
126 | case VIEW_TYPE_TEXT_IMAGE:
127 | return (V) new TextImageViewHolder(parent);
128 | case VIEW_TYPE_CARD:
129 | return (V) new CardRecordHolder(parent);
130 | default:
131 | return (V) new TextViewHolder(parent);
132 | }
133 | }
134 |
135 | @Override
136 | public boolean onCreateOptionsMenu(Menu menu) {
137 | getMenuInflater().inflate(R.menu.main_activity, menu);
138 | return super.onCreateOptionsMenu(menu);
139 | }
140 |
141 | @Override
142 | public boolean onOptionsItemSelected(MenuItem item) {
143 | if (item.getItemId() == R.id.multi_adapter) {
144 | startActivity(new Intent(this, MultiTypeActivity.class));
145 | return true;
146 | }
147 | return super.onOptionsItemSelected(item);
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/demo/src/main/java/cn/lemon/recyclerview/ui/ImageViewHolder.java:
--------------------------------------------------------------------------------
1 | package cn.lemon.recyclerview.ui;
2 |
3 | import android.util.Log;
4 | import android.view.ViewGroup;
5 | import android.widget.ImageView;
6 |
7 | import com.bumptech.glide.Glide;
8 |
9 | import cn.lemon.recyclerview.R;
10 | import cn.lemon.view.adapter.BaseViewHolder;
11 |
12 | /**
13 | * Created by linlongxin on 2016/8/23.
14 | */
15 |
16 | public class ImageViewHolder extends BaseViewHolder {
17 |
18 | private ImageView mImage;
19 |
20 | public ImageViewHolder(ViewGroup parent) {
21 | super(parent, R.layout.holder_image);
22 | }
23 |
24 | @Override
25 | public void onInitializeView() {
26 | super.onInitializeView();
27 | mImage = findViewById(R.id.image);
28 | }
29 |
30 | @Override
31 | public void setData(String object) {
32 | super.setData(object);
33 | Glide.with(itemView.getContext())
34 | .load(object)
35 | .into(mImage);
36 | }
37 |
38 | @Override
39 | public void onItemViewClick(String object) {
40 | super.onItemViewClick(object);
41 | Log.i("ImageViewHolder","onItemViewClick");
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/demo/src/main/java/cn/lemon/recyclerview/ui/MainActivity.java:
--------------------------------------------------------------------------------
1 | package cn.lemon.recyclerview.ui;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.os.Handler;
6 | import android.support.design.widget.FloatingActionButton;
7 | import android.support.v7.app.AppCompatActivity;
8 | import android.support.v7.widget.GridLayoutManager;
9 | import android.support.v7.widget.LinearLayoutCompat;
10 | import android.support.v7.widget.Toolbar;
11 | import android.view.Gravity;
12 | import android.view.Menu;
13 | import android.view.MenuItem;
14 | import android.view.ViewGroup;
15 | import android.widget.TextView;
16 |
17 | import cn.alien95.util.Utils;
18 | import cn.lemon.recyclerview.R;
19 | import cn.lemon.recyclerview.ui.bean.Consumption;
20 | import cn.lemon.view.RefreshRecyclerView;
21 |
22 |
23 | public class MainActivity extends AppCompatActivity {
24 |
25 | private RefreshRecyclerView mRecyclerView;
26 | private CardRecordAdapter mAdapter;
27 | private Handler mHandler;
28 | private int page = 1;
29 |
30 | @Override
31 | protected void onCreate(Bundle savedInstanceState) {
32 | super.onCreate(savedInstanceState);
33 | setContentView(R.layout.activity_main);
34 |
35 | mHandler = new Handler();
36 | Toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar);
37 | setSupportActionBar(mToolbar);
38 | FloatingActionButton mFab = (FloatingActionButton) findViewById(R.id.fab);
39 |
40 | mAdapter = new CardRecordAdapter(this);
41 |
42 | //添加Header
43 | final TextView textView = new TextView(this);
44 | textView.setLayoutParams(new LinearLayoutCompat.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, Utils.dip2px(48)));
45 | textView.setTextSize(16);
46 | textView.setGravity(Gravity.CENTER);
47 | textView.setText("重庆邮电大学");
48 | mAdapter.setHeader(textView);
49 | //添加footer
50 | final TextView footer = new TextView(this);
51 | footer.setLayoutParams(new LinearLayoutCompat.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, Utils.dip2px(48)));
52 | footer.setTextSize(16);
53 | footer.setGravity(Gravity.CENTER);
54 | footer.setText("-- Footer --");
55 | mAdapter.setFooter(footer);
56 |
57 | mRecyclerView = (RefreshRecyclerView) findViewById(R.id.recycler_view);
58 | mRecyclerView.setSwipeRefreshColors(0xFF437845, 0xFFE44F98, 0xFF2FAC21);
59 | mRecyclerView.setLayoutManager(new GridLayoutManager(this,2));
60 | mRecyclerView.setAdapter(mAdapter);
61 | mRecyclerView.addRefreshAction(() -> getData(true));
62 |
63 | mRecyclerView.addLoadMoreAction(() -> {
64 | getData(false);
65 | page++;
66 | });
67 |
68 | mRecyclerView.addLoadMoreErrorAction(() -> {
69 | getData(false);
70 | page++;
71 | });
72 |
73 | mRecyclerView.post(() -> {
74 | mRecyclerView.showSwipeRefresh();
75 | getData(true);
76 | });
77 |
78 | mFab.setOnClickListener(v -> mAdapter.remove(1));
79 |
80 | }
81 |
82 | public void getData(final boolean isRefresh) {
83 | mHandler.postDelayed(() -> {
84 | if (isRefresh) {
85 | page = 1;
86 | mAdapter.clear();
87 | mAdapter.addAll(getVirtualData());
88 | mRecyclerView.dismissSwipeRefresh();
89 | mRecyclerView.getRecyclerView().scrollToPosition(0);
90 | } else if (page == 3) {
91 | mAdapter.showLoadMoreError();
92 | } else {
93 | mAdapter.addAll(getVirtualData());
94 | if (page >= 5) {
95 | mRecyclerView.showNoMore();
96 | }
97 | }
98 | }, 1500);
99 | }
100 |
101 | public Consumption[] getVirtualData() {
102 | return new Consumption[]{
103 | new Consumption("Demo", "2015-12-18 12:09", "消费", 9.7f, 24.19f, "兴业源三楼"),
104 | new Consumption("Demo", "2015-12-18 12:09", "消费", 9.7f, 24.19f, "兴业源三楼"),
105 | new Consumption("Demo", "2015-12-18 12:09", "消费", 9.7f, 24.19f, "兴业源三楼"),
106 | new Consumption("Demo", "2015-12-18 12:09", "消费", 9.7f, 24.19f, "兴业源三楼"),
107 | new Consumption("Demo", "2015-12-18 12:09", "消费", 9.7f, 24.19f, "兴业源三楼"),
108 | new Consumption("Demo", "2015-12-18 12:09", "消费", 9.7f, 24.19f, "兴业源三楼"),
109 | new Consumption("Demo", "2015-12-18 12:09", "消费", 9.7f, 24.19f, "兴业源三楼"),
110 | new Consumption("Demo", "2015-12-18 12:09", "消费", 9.7f, 24.19f, "兴业源三楼"),
111 | new Consumption("Demo", "2015-12-18 12:09", "消费", 9.7f, 24.19f, "兴业源三楼"),
112 | new Consumption("Demo", "2015-12-18 12:09", "消费", 9.7f, 24.19f, "兴业源三楼")
113 | };
114 | }
115 |
116 | @Override
117 | public boolean onCreateOptionsMenu(Menu menu) {
118 | getMenuInflater().inflate(R.menu.main_activity, menu);
119 | return super.onCreateOptionsMenu(menu);
120 | }
121 |
122 | @Override
123 | public boolean onOptionsItemSelected(MenuItem item) {
124 | if (item.getItemId() == R.id.multi_adapter) {
125 | startActivity(new Intent(this, CustomMultiTypeActivity.class));
126 | return true;
127 | }
128 | return super.onOptionsItemSelected(item);
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/demo/src/main/java/cn/lemon/recyclerview/ui/MultiTypeActivity.java:
--------------------------------------------------------------------------------
1 | package cn.lemon.recyclerview.ui;
2 |
3 | import android.support.design.widget.FloatingActionButton;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.os.Bundle;
6 | import android.support.v7.widget.LinearLayoutManager;
7 | import android.support.v7.widget.Toolbar;
8 | import android.view.View;
9 | import cn.lemon.recyclerview.R;
10 | import cn.lemon.recyclerview.ui.bean.Consumption;
11 | import cn.lemon.recyclerview.ui.bean.TextImage;
12 | import cn.lemon.view.RefreshRecyclerView;
13 | import cn.lemon.view.adapter.Action;
14 | import cn.lemon.view.adapter.MultiTypeAdapter;
15 |
16 | public class MultiTypeActivity extends AppCompatActivity {
17 |
18 | private RefreshRecyclerView mRecyclerView;
19 | private MultiTypeAdapter mAdapter;
20 | private int mPage = 0;
21 |
22 | @Override
23 | protected void onCreate(Bundle savedInstanceState) {
24 | super.onCreate(savedInstanceState);
25 | setContentView(R.layout.activity_multi_type);
26 |
27 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
28 | setSupportActionBar(toolbar);
29 |
30 | mRecyclerView = (RefreshRecyclerView) findViewById(R.id.recycler_view);
31 | mRecyclerView.setSwipeRefreshColors(0xFF437845, 0xFFE44F98, 0xFF2FAC21);
32 | mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
33 | mAdapter = new MultiTypeAdapter(this);
34 | mRecyclerView.setAdapter(mAdapter);
35 | mRecyclerView.addRefreshAction(() -> getData(true));
36 | mRecyclerView.addLoadMoreAction(() -> getData(false));
37 | mRecyclerView.addLoadMoreErrorAction(() -> getData(false));
38 | mRecyclerView.post(() -> {
39 | mRecyclerView.showSwipeRefresh();
40 | getData(true);
41 | });
42 |
43 | FloatingActionButton mFab = (FloatingActionButton) findViewById(R.id.fab);
44 | mFab.setOnClickListener(v -> mAdapter.add(ImageViewHolder.class, getImageVirtualData()));
45 | }
46 |
47 | public void getData(final boolean isRefresh) {
48 | if (isRefresh) {
49 | mPage = 1;
50 | } else {
51 | mPage++;
52 | }
53 | if (mPage == 3) {
54 | mAdapter.showLoadMoreError();
55 | return;
56 | }
57 | mRecyclerView.postDelayed(() -> {
58 | if (isRefresh) {
59 | mAdapter.clear();
60 | mRecyclerView.dismissSwipeRefresh();
61 | }
62 | mAdapter.add(ImageViewHolder.class, getImageVirtualData());
63 | mAdapter.addAll(TextViewHolder.class, getTextVirtualData());
64 | mAdapter.addAll(TextImageViewHolder.class, getTextImageVirualData());
65 | mAdapter.addAll(CardRecordHolder.class, getRecordVirtualData());
66 | if (mPage >= 5) {
67 | mAdapter.showNoMore();
68 | }
69 | if (isRefresh) {
70 | mRecyclerView.getRecyclerView().scrollToPosition(0);
71 | }
72 | }, 1000);
73 | }
74 |
75 | public String getImageVirtualData() {
76 | return "http://i03.pictn.sogoucdn.com/3c28af542f2d49f7-fe9c78d2ff4ac332-73d7732e20e2fcfaa954979d623bcbe9_qq";
77 | }
78 |
79 | public String[] getTextVirtualData() {
80 | return new String[]{
81 | "算机相关知识科普博客还有他",
82 | "技术职级规律越来越摸"
83 | };
84 | }
85 |
86 | public TextImage[] getTextImageVirualData() {
87 | return new TextImage[]{
88 | new TextImage("http://i03.pictn.sogoucdn.com/3c28af542f2d49f7-9e7c5d699eaea93e-3f7e1bcc57cbe10e050bf58559b0d5ae_qq", "小猫咪"),
89 | new TextImage("http://i03.pictn.sogoucdn.com/3c28af542f2d49f7-8f0182a4cf50287e-ba43c5aef499c64e6a3297c5c500c7dc_qq", "那些年,我还是帅哥"),
90 | new TextImage("http://img02.sogoucdn.com/app/a/100520093/803d8006b5d521bb-2eb356b9e8bc4ae6-0725fb0ad48d8b3a32f08eb150380bba.jpg", "看片。。。")
91 | };
92 | }
93 |
94 | public Consumption[] getRecordVirtualData() {
95 | return new Consumption[]{
96 | new Consumption("Demo", "2015-12-18 12:09", "消费", 9.7f, 24.19f, "兴业源三楼"),
97 | new Consumption("Demo", "2015-12-18 12:09", "消费", 9.7f, 24.19f, "兴业源三楼"),
98 | new Consumption("Demo", "2015-12-18 12:09", "消费", 9.7f, 24.19f, "兴业源三楼"),
99 | new Consumption("Demo", "2015-12-18 12:09", "消费", 9.7f, 24.19f, "兴业源三楼")
100 | };
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/demo/src/main/java/cn/lemon/recyclerview/ui/TextImageViewHolder.java:
--------------------------------------------------------------------------------
1 | package cn.lemon.recyclerview.ui;
2 |
3 | import android.view.ViewGroup;
4 | import android.widget.ImageView;
5 | import android.widget.TextView;
6 |
7 | import com.bumptech.glide.Glide;
8 |
9 | import cn.lemon.recyclerview.R;
10 | import cn.lemon.recyclerview.ui.bean.TextImage;
11 | import cn.lemon.view.adapter.BaseViewHolder;
12 |
13 | /**
14 | * Created by linlongxin on 2016/8/23.
15 | */
16 |
17 | public class TextImageViewHolder extends BaseViewHolder {
18 |
19 | private TextView mText;
20 | private ImageView mImage;
21 |
22 | public TextImageViewHolder(ViewGroup parent) {
23 | super(parent, R.layout.holder_text_image);
24 | }
25 |
26 | @Override
27 | public void onInitializeView() {
28 | super.onInitializeView();
29 | mText = findViewById(R.id.text);
30 | mImage = findViewById(R.id.image);
31 | }
32 |
33 | @Override
34 | public void setData(TextImage object) {
35 | super.setData(object);
36 | mText.setText(object.text);
37 | Glide.with(itemView.getContext())
38 | .load(object.image)
39 | .into(mImage);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/demo/src/main/java/cn/lemon/recyclerview/ui/TextViewHolder.java:
--------------------------------------------------------------------------------
1 | package cn.lemon.recyclerview.ui;
2 |
3 | import android.util.Log;
4 | import android.view.Gravity;
5 | import android.view.ViewGroup;
6 | import android.widget.FrameLayout;
7 | import android.widget.TextView;
8 |
9 | import cn.lemon.view.adapter.BaseViewHolder;
10 |
11 | public class TextViewHolder extends BaseViewHolder {
12 |
13 | private TextView mText;
14 |
15 | public TextViewHolder(ViewGroup parent) {
16 | super(new TextView(parent.getContext()));
17 | mText = (TextView) itemView;
18 | mText.setTextSize(16f);
19 | mText.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
20 | mText.setGravity(Gravity.CENTER);
21 | mText.setPadding(24,24,24,24);
22 | }
23 |
24 | @Override
25 | public void onInitializeView() {
26 | super.onInitializeView();
27 | }
28 |
29 | @Override
30 | public void setData(String object) {
31 | super.setData(object);
32 | mText.setText(object);
33 | }
34 |
35 | @Override
36 | public void onItemViewClick(String object) {
37 | Log.i("TextViewHolder","onItemViewClick");
38 | }
39 | }
40 |
41 |
--------------------------------------------------------------------------------
/demo/src/main/java/cn/lemon/recyclerview/ui/bean/Consumption.java:
--------------------------------------------------------------------------------
1 | package cn.lemon.recyclerview.ui.bean;
2 |
3 | /**
4 | * Created by linlongxin on 2016/1/26.
5 | */
6 | public class Consumption {
7 |
8 | private String xm;
9 | private String sj;
10 | private String lx;
11 | private float je;
12 | private float ye;
13 | private String sh;
14 |
15 | public Consumption(String xm, String sj, String lx, float je, float ye, String sh) {
16 | this.xm = xm;
17 | this.sj = sj;
18 | this.lx = lx;
19 | this.je = je;
20 | this.ye = ye;
21 | this.sh = sh;
22 | }
23 |
24 | public String getSj() {
25 | return sj;
26 | }
27 |
28 | public String getLx() {
29 | return lx;
30 | }
31 |
32 | public float getJe() {
33 | return je;
34 | }
35 |
36 | public float getYe() {
37 | return ye;
38 | }
39 |
40 | public String getSh() {
41 | return sh;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/demo/src/main/java/cn/lemon/recyclerview/ui/bean/TextImage.java:
--------------------------------------------------------------------------------
1 | package cn.lemon.recyclerview.ui.bean;
2 |
3 | /**
4 | * Created by linlongxin on 2016/8/23.
5 | */
6 |
7 | public class TextImage {
8 | public String image;
9 | public String text;
10 |
11 | public TextImage(String image, String text) {
12 | this.image = image;
13 | this.text = text;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/demo/src/main/res/drawable/bg_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
--------------------------------------------------------------------------------
/demo/src/main/res/drawable/ic_detele.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhazhaxin/RecyclerView/12f78097b557fa91144164718077a99ac50f50bb/demo/src/main/res/drawable/ic_detele.png
--------------------------------------------------------------------------------
/demo/src/main/res/layout/activity_custom_multi_type.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
16 |
17 |
20 |
21 |
25 |
26 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
16 |
17 |
20 |
21 |
25 |
26 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/activity_multi_type.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
16 |
17 |
20 |
21 |
25 |
26 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/fragment_consume.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/holder_consume.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
16 |
17 |
25 |
26 |
35 |
36 |
43 |
44 |
45 |
53 |
54 |
62 |
63 |
70 |
71 |
77 |
78 |
83 |
84 |
85 |
86 |
91 |
92 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/holder_image.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
14 |
18 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/holder_text_image.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
19 |
20 |
27 |
28 |
29 |
33 |
34 |
--------------------------------------------------------------------------------
/demo/src/main/res/menu/main_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhazhaxin/RecyclerView/12f78097b557fa91144164718077a99ac50f50bb/demo/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhazhaxin/RecyclerView/12f78097b557fa91144164718077a99ac50f50bb/demo/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhazhaxin/RecyclerView/12f78097b557fa91144164718077a99ac50f50bb/demo/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhazhaxin/RecyclerView/12f78097b557fa91144164718077a99ac50f50bb/demo/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhazhaxin/RecyclerView/12f78097b557fa91144164718077a99ac50f50bb/demo/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/demo/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3ebc61
4 | #2fac21
5 | #d71c78
6 |
7 | #5675de
8 |
9 | @color/grey
10 |
11 | #e0e0e0
12 |
13 |
--------------------------------------------------------------------------------
/demo/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/demo/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Demo
3 |
4 |
--------------------------------------------------------------------------------
/demo/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhazhaxin/RecyclerView/12f78097b557fa91144164718077a99ac50f50bb/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu Mar 29 14:27:36 CST 2018
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/screenshot/MultiTypeAdapter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhazhaxin/RecyclerView/12f78097b557fa91144164718077a99ac50f50bb/screenshot/MultiTypeAdapter.png
--------------------------------------------------------------------------------
/screenshot/RecyclerAdapter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhazhaxin/RecyclerView/12f78097b557fa91144164718077a99ac50f50bb/screenshot/RecyclerAdapter.png
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':demo', ':RefreshRecyclerView'
2 |
--------------------------------------------------------------------------------