关于ListView上拉刷新的需求很多,实现方式也多种多样。
一般是简单的通过一个page变量来控制当前请求的页数,然后上拉的时候就发送请求。
实现出来后,经过测试哥的折腾,发现有诸多细节没有处理好,比如会出现重复数据,反复的上拉导致多次请求等bug。
后来就决定单独写一个工具类,方便以后需要直接使用。
1 public class ListViewScrollHelper{ 2 private static final String TAG = "ListViewScrollHelper"; 3 private static final int LIST_PAGE_SIZE = 15; 4 5 private NextPage nextPage; 6 private InitAdapter initAdapter; 7 8 private int pageIndex = -1; 9 private int totalPage; 10 11 private ListView lv_goodsList; 12 private BaseAdapter goodsAdapter; 13 private List goodsList = new ArrayList<>(); 14 private Semaphore semaphore = new Semaphore(0); 15 16 public ListViewScrollHelper(ListView lv_goodsList, InitAdapter initAdapter, NextPage nextPage) { 17 this.initAdapter = initAdapter; 18 this.lv_goodsList = lv_goodsList; 19 this.nextPage = nextPage; 20 initView(); 21 } 22 23 private void initView() { 24 goodsAdapter = initAdapter.initAdapter(goodsList); 25 lv_goodsList.setAdapter(goodsAdapter); 26 lv_goodsList.setOnScrollListener(new AbsListView.OnScrollListener() { 27 @Override 28 public void onScrollStateChanged(AbsListView view, int scrollState) { 29 } 30 31 @Override 32 public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { 33 34 // 判断是否到底部了 35 if (firstVisibleItem + visibleItemCount == totalItemCount && totalItemCount > 0) { 36 Log.d(TAG, String.valueOf(pageIndex)); 37 if (hasNextPage() && canRequestNextPage()) { 38 pageIndex++; 39 if (nextPage != null) 40 nextPage.next(); 41 } else { 42 Log.d(TAG, "列表已经到底部!"); 43 } 44 } 45 } 46 }); 47 } 48 49 /** 50 * 此函数将会作为分页刷新数据的主函数 51 * 内部将会实现 根据当前页数判断是否重置数据 或者 继续下一页 52 * 如果重置数据,初始化起始页需要使用函数 resetPageIndex() 53 * 54 * @param list 55 * @param totalSize 56 */ 57 public void refreshPage(List list, int totalSize) { 58 if (pageIndex < 0) { 59 initData(list, totalSize); 60 } else { 61 freshList(list); 62 } 63 } 64 65 /** 66 * 如果有多处控制一个listview数据内容(比如:分类,搜索都能控制商品列表展示) 67 * ,此时可以使用此函数设置分页信息 68 * 69 * @param list 70 * @param totalSize 71 */ 72 public void initData(List list, int totalSize) { 73 pageIndex = 0; 74 goodsList.clear(); 75 76 if (totalSize > LIST_PAGE_SIZE) { 77 totalPage = totalSize / LIST_PAGE_SIZE; 78 if (totalSize % LIST_PAGE_SIZE >= 1) 79 totalPage++; 80 Log.d("wbl", "totalPage:" + totalPage); 81 } else { 82 totalPage = 1; 83 } 84 85 freshList(list); 86 } 87 88 /** 89 * 设置下一面的数据 90 * 91 * @param list 92 * @param type (此字段废弃) 93 */ 94 public void nextPage(List list, int type) { 95 freshList(list); 96 } 97 98 /** 99 * 当请求失败时,恢复上到一页100 */101 public void restoreLastPage() {102 if (!canRequestNextPage()) {103 if (pageIndex > 0) pageIndex--;104 }105 semaphore.release();106 }107 108 private boolean hasNextPage() {109 return pageIndex < totalPage - 1;110 }111 112 public int getPageIndex() {113 return pageIndex < 0 ? 0 : pageIndex;114 }115 116 public int getPageIndex(boolean hasCategoryChange) {117 if (hasCategoryChange)118 pageIndex = 0;119 return getPageIndex();120 }121 122 /**123 * 重置分页参数124 */125 public void resetPageIndex() {126 pageIndex = -1;127 totalPage = 0;128 }129 130 public void setEmptyView(View view) {131 lv_goodsList.setEmptyView(view);132 }133 134 /**135 * @param list 传入要显示的list136 */137 private void freshList(List list) {138 if (list != null && list.size() > 0) {139 goodsList.addAll(list);140 }141 goodsAdapter.notifyDataSetChanged();142 semaphore.release();143 }144 145 private boolean canRequestNextPage() {146 return semaphore.tryAcquire();147 }148 149 public List getGoodsList() {150 return goodsList;151 }152 153 public interface NextPage {154 void next();155 }156 157 public interface InitAdapter {158 BaseAdapter initAdapter(List list);159 }160 }
详细使用可以参考这个项目