關於ListView上拉刷新的需求很多,實現方式也多種多樣。
一般是簡單的通過一個page變量來控制當前請求的頁數,然后上拉的時候就發送請求。
實現出來后,經過測試哥的折騰,發現有諸多細節沒有處理好,比如會出現重復數據,反復的上拉導致多次請求等bug。
后來就決定單獨寫一個工具類,方便以后需要直接使用。
1 public class ListViewScrollHelper<T> { 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<T> 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 傳入要顯示的list 136 */ 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<T> getGoodsList() { 150 return goodsList; 151 } 152 153 public interface NextPage { 154 void next(); 155 } 156 157 public interface InitAdapter<T> { 158 BaseAdapter initAdapter(List<T> list); 159 } 160 }
詳細使用可以參考這個項目
https://github.com/awenblue/ListViewScroll