android ListView结合xutils3仿微信实现下拉加载更多
作者:青楼爱小生 发布时间:2023-11-29 11:11:50
前言:最近涉及到和QQ打交道,定义所有的好友一共只能有300条消息,如果一次性从数据库读取300条或者更多,界面会有细微的卡顿.所以考虑了下分页,第一次进来只显示20条(仿微信),当用户滑到第一条后,如果数据库有消息,则再加载20条.
步骤-问把大象关冰箱,总共分几步?
1.自定义absListview.scrollListerner
核心的东西是监听ListView的scrollListerner,这里采取拿来主义 原文连接找不到了,如果原作者看到,请联系青楼爱小生,将您的文章链接更新出来 ,网上扒了一个挺不错的,大家用的时候实现这个scrollListerner,完善自己的逻辑即可
public class MyOnScrollListener implements OnScrollListener {
private int totalItemCount;
//ListView最后的item项
private int lastItem;
//listview第一项
private int firstItem;
//用于判断当前是否在加载
private boolean isLoading;
//底部加载更多布局
private View footer;
//接口回调的实例
private OnloadDataListener listener;
//数据
private List<MsgBean> data;
Handler handler = new Handler();
public MyOnScrollListener(View footer, List<MsgBean> data) {
this.footer = footer;
this.data = data;
}
//设置接口回调的实例
public void setOnLoadDataListener(OnloadDataListener listener) {
this.listener = listener;
}
/**
* 滑动状态变化
*
* @param view
* @param scrollState 1 SCROLL_STATE_TOUCH_SCROLL是拖动 2 SCROLL_STATE_FLING是惯性滑动 0SCROLL_STATE_IDLE是停止 , 只有当在不同状态间切换的时候才会执行
*/
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
//如果数据没有加载,并且滑动状态是停止的,并且滚到了第一个item,可在此做下拉更新或者上拉更新的判断
if (!isLoading && firstItem == 0 && scrollState == SCROLL_STATE_IDLE) {
//显示加载更多
footer.setVisibility(View.VISIBLE);
//模拟一个延迟两秒的刷新功能
handler.postDelayed(new Runnable() {
@Override
public void run() {
if (listener != null) {
//开始加载更多数据
loadMoreData();
//回调设置ListView的数据
listener.onLoadData(data);
//加载完成后操作什么
loadComplete();
}
}
}, 2000);
}
}
/**
* 当加载数据完成后,设置加载标志为false表示没有加载数据了
* 并且设置底部加载更多为隐藏
*/
private void loadComplete() {
isLoading = false;
footer.setVisibility(View.GONE);
}
/**
* 开始加载更多新数据,这里每次只更新三条数据
*/
private void loadMoreData() {
isLoading = true;
MsgBean msg = null;
for (int i = 0; i < 3; i++) {
msg = new MsgBean();
msg .setRemark("Liming"+i);
msg .setMsgID(i);
data.add(stu);
}
}
/**
* 监听可见界面的情况
*
* @param view ListView
* @param firstVisibleItem 第一个可见的 item 的索引
* @param visibleItemCount 可以显示的 item的条数
* @param totalItemCount 总共有多少个 item
*/
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
//实现下拉加载
lastItem = firstVisibleItem + visibleItemCount;
//实现上拉加载
firstItem = firstVisibleItem;
//总listView的item个数
this.totalItemCount = totalItemCount;
}
//回调接口
public interface OnloadDataListener {
void onLoadData(List<MsgBean> data);
}
}
2.实现此接口
public class ListPageActivity extends Activity implements MyOnScrollListener.OnloadDataListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_page);
//显示到ListView上
showListView(data);
//自定义的滚动监听事件
MyOnScrollListener onScrollListener = new MyOnScrollListener(header, data);
//设置接口回调
onScrollListener.setOnLoadDataListener(this);
//设置ListView的滚动监听事件
mListView.setOnScrollListener(onScrollListener);
@Override
public void onLoadData(List<MsgBean> data) {
//加载数据完成后,展示数据到ListView
showListView(data);
}
}
showListView里面无疑是普通的更新adapter的工作
那么我们如何借助xutils的数据库进行分类呢?
3.利用xutils数据库操作进行分页处理
首先,我们理一下思路,上面我们已经实现了上拉的回调,在此回调中把新来的数据加载到adapter即可.
下文db是Dbmanager的实例
/**
* 当前屏幕显示的消息数量
*/
private int MAX_MSG_NUMBER = 20;
private List<MsgBean> getDataFromDb() {
List<?> dbSize = db.selector(MsgBean.class).where(WhereBuilder.b("id", "=", 400)).findAll();//记得捕获null指针和DbException异常
//如果数据库比我们显示的页数小,则不偏移,否则,偏移到我们需要显示的位置
if (dbSize.size() < MAX_MSG_NUMBER) {
indexOffset = 0;
} else {
indexOffset = dbSize.size() - MAX_MSG_NUMBER;
}
List<MsgBean> datas = db.selector(MsgBean.class).where(WhereBuilder.b("id", "=", 400)).limit(MAX_MSG_NUMBER)
.offset(indexOffset).findAll();
return datas;
}
这里解释一下
db.selector(MsgBean.class).where(WhereBuilder.b("id", "=", 400)).limit(MAX_MSG_NUMBER).offset(indexOffset).findAll();是我们实现分页的关键
.limit是我们定义的分页大小
.offset偏移量,我们数据库的大小是不变的,如果不定义偏移量,那么我们定义的分页大小每次只从0取到19.假设数据库中有21条数据,那么我们需要从1取到20,而不是0到19,所以偏移1.
然后我们在loadMoreData中
MAX_MSG_NUMBER += MAX_MSG_NUMBER;
getDataFromDb();
将大小自加,即完成加载更多的功能,在onLoadData(List<MsgBean> data)中加载数据即可.
后面贴上我对xutils数据库操作的封装,还有很多不完善之处
/**
* 数据库 xutils用法
* @author 青楼爱小生
*/
public class DbUtil {
private static final String TAG = DbUtil.class.getName();
private static DbUtil dbUtil;
private DbManager db;
private DbUtil(){
db = x.getDb(MyApplication.getInstance().daoConfig);
}
public static DbUtil getInstance(){
if(dbUtil == null){
synchronized (DbUtil.class) {
if(dbUtil == null){
dbUtil = new DbUtil();
}
}
}
return dbUtil;
}
/**
* 增加数据
* @param list
* @throws DbException
*/
public void addMsgList(List<MsgBean> list) {
try {
db.saveOrUpdate(list);
} catch (DbException e) {
e.printStackTrace();
LogHelper.e(TAG, e.getMessage());
}
}
/**
* 增加一条数据
* @param node
* @throws DbException
*/
public void addMsgToDb(MsgBean node) {
try {
db.saveOrUpdate(node);
} catch (DbException e) {
e.printStackTrace();
LogHelper.e(TAG, e.getMessage());
}
}
/**
* 删除表中所有数据
* @param cls 创建的表的映射
* @throws DbException
*/
public void deleteAll(Class cls) {
try {
db.delete(cls);
} catch (DbException e) {
LogHelper.e(TAG, e.getMessage());
e.printStackTrace();
}
}
/**
* 删除第一条数据
* @param cls
*/
@SuppressWarnings("unchecked")
public void deleteFirst(Class cls){
try {
db.delete(db.findFirst(cls));
} catch (DbException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 查询表中所有数据
* @throws DbException
*/
@SuppressWarnings("unchecked")
public List<?> findAll(Class cls) {
try {
return db.findAll(cls) == null ? Collections.emptyList() : db.findAll(cls);
} catch (DbException e) {
e.printStackTrace();
LogHelper.e(TAG, e.getMessage());
return Collections.emptyList();
}
}
/**
* //添加查询条件进行查询
List<ChildInfo> all = db.selector(ChildInfo.class).where("id",">",2).and("id","<",4).findAll();
* @return 搜索指定条件的数据
*/
@SuppressWarnings("unchecked")
public List<?> findDataByWhere(Class cls,WhereBuilder format){
try {
return db.selector(cls).where(format).findAll()== null ?
Collections.emptyList() :db.selector(cls).where(format).findAll();
} catch (DbException e) {
LogHelper.e(TAG, e.getMessage());
e.printStackTrace();
return Collections.emptyList();
}
}
/**
* 添加查询条件进行查询
* @param cls 表映射
* @param str select语句
* @param format where语句
* @return List<DbModel> DbModel key为数据库列名 value为值
* eg:(Selector.from(Parent.class)
.where("id" ,"<", 54)
.and(WhereBuilder.b("age", ">", 20).or("age", " < ", 30))
.orderBy("id")
.limit(pageSize) .offset(pageSize * pageIndex));
*
*
*
*/
@SuppressWarnings("unchecked")
public Selector<?> findDataBySelector(Class cls,WhereBuilder format){
try {
return db.selector(cls).where(format);
} catch (DbException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
来源:http://www.jianshu.com/p/16a20f25b1c8


猜你喜欢
- 目录安装 BenchmarkDotNet什么是基准测试创建基准测试代码运行 benchmarkBenchmarkDotNet 是一个轻量级,
- 概念所谓回文串,就是字符串反转以后和原串相同,如 abba 和 lippil。对于回文串还是比较容易去验证的,从字符数组的两端开始向中间靠拢
- 程序员日常工作中,发送http请求特别常见。本文以Java为例,总结发送http请求的多种方式。1. HttpURLConnection使用
- Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements)。一些
- Spring定时任务无故停止又不报错一开始是使用Spring自带的定时器来配置定时任务的,简单快捷,配置如下:<bean id=&qu
- 简单介绍2020年注定是不平凡的一年,新冠肺炎肆虐全球,传染性特别强,目前全球感人人数还在逐渐攀升,作为中华儿女特别感谢政府作出的努力,非常
- 1、代码就一个Controller,从官网复制过来的,如下package com.springboot.controller;import
- 一、简介1、AutoCompleteTextView的作用 2、AutoCompleteTextView的类结构图也就是拥有Edi
- 本文实例为大家分享了C语言运用函数指针数组制作计算器的具体代码,供大家参考,具体内容如下先来回顾一下概念:指针数组 —— 存放指针的数组函数
- /* String name = "adsbsadgsadgtewterfsdf"
- 使用 WebView 时,我们通常会重写以下方法:shouldOverrideUrlLoading() onPageStarted()onP
- 本文实例讲述了Android编程实现自定义ProgressBar样式。分享给大家供大家参考,具体如下:效果图如下,本例中设置了第一级进度条和
- 本文实例为大家分享了C++实现扫雷游戏的具体代码,供大家参考,具体内容如下#include<stdio.h>#include&l
- 算法如下: 基姆拉尔森计算公式W= (d+2*m+3*(m+1)/5+y+y/4-y/100+y/400) mod 7 在公式中
- 今天遇到了一个比较有意思的问题,从服务器上封装好的java.sql.timestamp对象返回到本地客户端程序后与数据库中的时间相差了整整1
- java中next与nextLine用法区别:next()一定要读取到有效字符后才可以结束输入,对输入有效字符之前遇到的空格键、Tab键或E
- 实现的效果图:代码实现:tv = (TextView) findViewById(R.id.tv);String a = "有2年
- map中相同的key保存多个value值在java中,Map集合中只能保存一个相同的key,如果再添加相同的key,则之后添加的key的值会
- Druid是数据库连接池,它能够提供强大的监控和扩展功能。官方文档Spring Boot整合第三方技术的两种方式:自定义找starter场景
- /*冒泡排序:双层循环1.外层循环:控制排序轮数,排序数组长度减1(最后一次循环只剩下一个元素,不需要比较,同时数组已完成排序。2.内层循环