• Android ListView上拉获取下一页


        关于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

  • 相关阅读:
    COM编程-注册DLL形式的COM服务器
    控制台console使用MFC库函数,Cout输出CString的方法
    [C#]窗体切换--避免开启多个线程
    OpenCV配置使用版
    Dependency Walker使用说明
    TCP粘包和半包的处理方法
    GENERATED_UCLASS_BODY 和 GENERATED_BODY 区别
    c++ 的 坑真多之头文件
    Introduction to replication 翻译
    c++ 的 static_cast
  • 原文地址:https://www.cnblogs.com/AwenDF/p/5834537.html
Copyright © 2020-2023  润新知