Android之ListView分页加载数据功能实现代码
作者:qq_27630169 发布时间:2023-08-13 03:44:17
什么是ListView分页加载数据功能呢?在现在的大数据时代,我们不可能把某些数据全部展示到界面,好比我们经常会看的QQ空间一样,当你看动态的时候,系统不可能会把所有好友的动态都展示在上面,你能看到的一般都是最新好友更新的动态,假如你要看非最新的好友动态,通常你都会手指向上滑动屏幕然后去查看,当界面下滑到一定数量的时候,就会看到一个“查看更多”,然后突然停顿一下,系统会通过网络去给你刷新其他动态信息,这样的功能我们一般叫做数据下拉刷新功能,也就是我们的分页加载功能,具体的实现是怎样的呢?下面我们开始详细讲解。
实现的原理:
1. 首先要先确定默认展示在ListView上的数据,比如默认在ListView上展示10条数据。
2. 将数据传递到自定义的适配器上,然后加载到ListView中。
3. 当用户将数据拉到最后一条的时候,就要开始刷新加载新数据了。
4. 通过监听ListView的滑动事件,判断是否达到最后一条,如果达到最后一条则开始刷新。
详细的实现步奏在代码中详细讲解。
整体结构如下:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.company.listviewdeepknow.MainActivity">
<ListView
android:id="@+id/mList"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
</RelativeLayout>
foot_boot.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="70dp"
android:gravity="center"
android:orientation="horizontal">
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleSmall"
android:layout_width="45dp"
android:layout_height="45dp" />
<TextView
android:id="@+id/mLoad"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="加载更多..."
android:textSize="20sp" />
</LinearLayout>
list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:id="@+id/mTv1"
android:layout_width="100dp"
android:layout_height="100dp"
android:textSize="20sp" />
<TextView
android:id="@+id/mTv2"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_alignParentRight="true"
android:textSize="20sp" />
</RelativeLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity implements MyOnScrollListener.OnloadDataListener {
//ListView展示的数据项
private List<Student> data;
//ListView控件
private ListView mList;
//自定义适配器
MyAdapter adapter;
//底部加载更多布局
View footer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//首先加载默认数据,这里设置为10条
getData();
//显示到ListView上
showListView(data);
//自定义的滚动监听事件
MyOnScrollListener onScrollListener = new MyOnScrollListener(footer, data);
//设置接口回调
onScrollListener.setOnLoadDataListener(this);
//设置ListView的滚动监听事件
mList.setOnScrollListener(onScrollListener);
}
/**
* 初始化ListView数据,默认设置为10条
*/
private void getData() {
data = new ArrayList<>();
Student stu = null;
for (int i = 0; i < 10; i++) {
stu = new Student();
stu.setName("姓名" + i);
stu.setSex(i % 2 == 0 ? "男" : "女");
data.add(stu);
}
}
/**
* 将数据加载到ListView上
*
* @param data
*/
private void showListView(List<Student> data) {
//首先判断适配器是否为空,首次运行肯定是为空的
if (adapter == null) {
//查到ListView控件
mList = (ListView) findViewById(R.id.mList);
//将底部加载一个加载更多的布局
footer = LayoutInflater.from(this).inflate(R.layout.foot_boot, null);
//初始状态为隐藏
footer.setVisibility(View.GONE);
//加入到ListView的底部
mList.addFooterView(footer);
//创建adpter数据
adapter = new MyAdapter(data);
//设置adapter
mList.setAdapter(adapter);
} else {
//不为空,则刷新数据
this.data = data;
//提醒ListView重新更新数据
adapter.notifyDataSetChanged();
}
}
@Override
public void onLoadData(List<Student> data) {
//加载数据完成后,展示数据到ListView
showListView(data);
}
}
MyOnScrollListener.java
public class MyOnScrollListener implements AbsListView.OnScrollListener {
//ListView总共显示多少条
private int totalItemCount;
//ListView最后的item项
private int lastItem;
//用于判断当前是否在加载
private boolean isLoading;
//底部加载更多布局
private View footer;
//接口回调的实例
private OnloadDataListener listener;
//数据
private List<Student> data;
public MyOnScrollListener(View footer, List<Student> 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 && lastItem == totalItemCount && scrollState == SCROLL_STATE_IDLE) {
//显示加载更多
footer.setVisibility(View.VISIBLE);
Handler handler = new Handler();
//模拟一个延迟两秒的刷新功能
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;
Student stu = null;
for (int i = 0; i < 3; i++) {
stu = new Student();
stu.setName("新名字" + i);
stu.setSex("新性别" + 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) {
//当可见界面的第一个item + 当前界面多有可见的界面个数就可以得到最后一个item项了
lastItem = firstVisibleItem + visibleItemCount;
//总listView的item个数
this.totalItemCount = totalItemCount;
}
//回调接口
public interface OnloadDataListener {
void onLoadData(List<Student> data);
}
}
MyAdapter.java
public class MyAdapter extends MyBaseAdapter<Student> {
public MyAdapter(List<Student> data) {
super(data);
}
@Override
public void setData(ViewHolder holder, Student t) {
holder.setText(R.id.mTv1, t.getName()).setText(R.id.mTv2, t.getSex());
}
}
MyBaseAdapter.java
public abstract class MyBaseAdapter<T> extends BaseAdapter {
protected List<T> data;
public MyBaseAdapter(List<T> data){
this.data = data;
}
@Override
public int getCount() {
return data == null ? 0 : data.size();
}
@Override
public Object getItem(int position) {
return data.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = ViewHolder.getHolder(convertView,parent,position, R.layout.list_item);
setData(holder,data.get(position));
return holder.getConvertView();
}
public abstract void setData(ViewHolder holder,T t);
}
ViewHolder.java
public class ViewHolder {
private int position;
private SparseArray<View> array;
private View convertView;
private Context context;
private ViewHolder(ViewGroup parent, int position, int layout) {
this.position = position;
this.context = parent.getContext();
convertView = LayoutInflater.from(parent.getContext()).inflate(layout, null);
convertView.setTag(this);
array = new SparseArray<>();
}
public static ViewHolder getHolder(View convertView, ViewGroup parent, int position, int layout) {
if (convertView == null) {
return new ViewHolder(parent, position, layout);
} else {
ViewHolder holder = (ViewHolder) convertView.getTag();
holder.position = position;
return holder;
}
}
public <T extends View> T getView(int viewId) {
View view = array.get(viewId);
if (view == null) {
view = convertView.findViewById(viewId);
array.put(viewId, view);
}
return (T) view;
}
public View getConvertView() {
return convertView;
}
public ViewHolder setText(int viewId, String data) {
TextView tv = getView(viewId);
tv.setText(data);
return this;
}
Student.java
public class Student {
private String name;
private String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
除了MyAdapter.java MyBaseAdapter.java ViewHolder.java 以及 Student.java实体类没有注解,其他两个主要实现类都已经注释了,关于自定义通用适配器的讲解,本篇不做讲解,如果想了解如何实现自定义通用适配器知识的可以查看:
下面可以看看效果图:
猜你喜欢
- 单源最短路径问题,即在图中求出给定顶点到其它任一顶点的最短路径。在弄清楚如何求算单源最短路径问题之前,必须弄清楚最短路径的最优子
- 本文实例讲述了C#实现为一张大尺寸图片创建缩略图的方法。分享给大家供大家参考。具体实现方法如下:public static Bitmap C
- 一、对象与内存控制的知识点1.java变量的初始化过程,包括局部变量,成员变量(实例变量和类变量)。2.继承关系中,当使用的对象引用变量编译
- 前言博主上个礼拜,已经实现了quarkus的native image应用的上线,经过两天的监控下来,一切运行指标良好,就是内存升到了100M
- 目录前言示例参考:前言按需加载对象延迟加载实际是推迟进行创建对象,直到对其调用后才进行创建初始化,延迟(懒加载)的好处是提高系统性能,避免不
- 在平时的工作中,估计大多数都做过轮询调度的任务,比如定时轮询数据库同步,定时邮件通知等等。大家通过windows计划任务,windows服务
- 前言我们会使用git来保存我们项目的配置文件,但是文件中总有一些敏感数据,对于这些敏感数据我们通常需要给它加密,加密通常有两种加密方式,一种
- 一 概述GC(Garbage Collection),在程序运行过程中内存空间是有限的,为了更好的的使用有限的内存空间,GC会将不再使用的对
- 1.1、定义从现有类派生的类被称作子类,也叫派生类,扩展类,或孩子类。现有类被称作超类,也叫基类,或父类。1.2、创建子类public cl
- springboot多模块项目添加一新模块选择Maven Module,填写模块名若空白,catalog目录可选择internal更改包名完
- 需要的Maven<!--redis--> <dependency&g
- 介绍最近要使用播放器做一个简单的视频播放功能,开始学习VideoView,在横竖屏切换的时候碰到了点麻烦,不过在查阅资料后总算是解决了。在写
- 如何建立哈夫曼树的,网上搜索一堆,这里就不写了,直接给代码。1.哈夫曼树结点类:HuffmanNode.h#ifndef HuffmanNo
- 本文实例讲述了C#实现windows form拷贝内容到剪贴板的方法。分享给大家供大家参考。具体实现方法如下:using System;us
- 一.导入Netty依赖<dependency> <groupId>io.netty</group
- List list=new ArrayList()是怎么回事首先明确List是接口,ArrayList是它的实现类以下两种方法都可以,但是不
- 为什么要使用路由在之前我们的代码中,页面跳转使用的代码如下所示:Navigator.of(context).push( Mate
- 肝了两天,重新整理了下时间工具类,以后我就以该时间工具类进行项目开发了,后会不定期更新功能,也欢迎留言需求,让工具类不断的完善。常量介绍相关
- 指针是什么?指针(Pointer)是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址。换句话说就是可以通过指针找到以它为地址的内存
- 在日常的app使用中,我们会在android 的app中看见 热门标签等自动换行的流式布局,今天,我们就来看看如何自定义一个类似热门标签那样