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

时间: 2024-10-10 12:54:37

Android ListView上拉获取下一页的相关文章

Android MVP设计框架模板 之 漂亮ListView上拉刷新下拉加载更多

mvp的全称为Model-View-Presenter,Model提供数据,View负责显示,Controller/Presenter负责逻辑的处理.MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会直接从Model中读取数据而不是通过 Controller. 项目中大部分是面对接口编程,通过P层可以预先将所有需要的接口功能

android ListView上拉加载更多 下拉刷新功能实现(采用pull-to-refresh)

Android实现上拉加载更多功能以及下拉刷新功能, 采用了目前比较火的PullToRefresh,他是目前实现比较好的下拉刷新的类库. 目前他支持的控件有:ListView, ExpandableListView,GridView,WebView等. 下载地址:https://github.com/chrisbanes/Android-PullToRefresh 首先第一步当然是导入libriay到咱们的项目了,具体导入方式,这里不再赘述. 下面是个例子采用的是ListView,当然其余的和这

Android——Xlistview上拉刷新下拉加载

配置网络权限+xutils包+gson包 代码如下: values下修改strings添加 直接粘 <?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">XListView刷新</string> <string name="hello_world">Hello world!

Android PullToRefresh上拉和下拉刷新

Github链接: https://github.com/chrisbanes/Android-PullToRefresh 1. 设置Listview layout文件中定义PullToRefreshListView Xml代码 <com.jackie.PullToRefreshListView android:id="@+id/list_view" android:layout_width="match_parent" android:layout_heig

android自定义控件之ListView上拉加载与下拉刷新

自定义控件LoadLayout import android.content.Context; import android.graphics.drawable.Animatable; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.MotionEvent; import andr

ListView上拉加载和下拉刷新多种实现方式

ListView上拉加载和下拉刷新多种实现方式 该篇为ListView下拉刷新和上拉加载实现的各种方法大合集.可能在具体的细节逻辑上处理不太到位,但基本上完成逻辑的实现.细节方面,个人可以根据自己的需求进行完善. 该博客将以四种思路来完成下拉刷新和上拉加载 自定义View实现上拉加载和下拉刷新 使用PullToRefresh 实现上拉加载和下拉刷新 使用Ultra-Pull-To-Refresh实现上拉加载和下拉刷新 使用SwipeToRefreshLayout实现上拉加载和下拉刷新 如果你对L

ListView上拉加载下拉刷新

主要用到了这个几个文件,MainActivity是界面的Activity,MyAdapter是ListView的自定义适配,MyListView是自定义带头部LIistView,如果只需要上拉加载就不需要:activity_main.xml是住界面,item.xml是ListView的子布局里面只有一个TextView,listview_footer.xml是listview的加载更多的底部布局,listview_header.xml是listview的头部布局. MainActivity.ja

android自定义控件之ListView上拉加载

自定义控件LoadLayout import android.content.Context; import android.graphics.drawable.Animatable; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.MotionEvent; import andr

Android之 RecyclerView,CardView 详解和相对应的上拉刷新下拉加载

随着 Google 推出了全新的设计语言 Material Design,还迎来了新的 Android 支持库 v7,其中就包含了 Material Design 设计语言中关于 Card 卡片概念的实现 -- CardView.RecyclerView也是谷歌V7包下新增的控件,用来替代ListView的使用,在RecyclerView标准化了ViewHolder类似于ListView中convertView用来做视图缓存. RecyclerView的优点就是,他可以通过设置LayoutMan