Android之ListView分页加载数据功能实现代码

作者:qq_27630169 时间:2023-08-13 03:44:17 

什么是ListView分页加载数据功能呢?在现在的大数据时代,我们不可能把某些数据全部展示到界面,好比我们经常会看的QQ空间一样,当你看动态的时候,系统不可能会把所有好友的动态都展示在上面,你能看到的一般都是最新好友更新的动态,假如你要看非最新的好友动态,通常你都会手指向上滑动屏幕然后去查看,当界面下滑到一定数量的时候,就会看到一个“查看更多”,然后突然停顿一下,系统会通过网络去给你刷新其他动态信息,这样的功能我们一般叫做数据下拉刷新功能,也就是我们的分页加载功能,具体的实现是怎样的呢?下面我们开始详细讲解。

实现的原理:

1. 首先要先确定默认展示在ListView上的数据,比如默认在ListView上展示10条数据。
2. 将数据传递到自定义的适配器上,然后加载到ListView中。
3. 当用户将数据拉到最后一条的时候,就要开始刷新加载新数据了。
4. 通过监听ListView的滑动事件,判断是否达到最后一条,如果达到最后一条则开始刷新。

详细的实现步奏在代码中详细讲解。

整体结构如下:

Android之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实体类没有注解,其他两个主要实现类都已经注释了,关于自定义通用适配器的讲解,本篇不做讲解,如果想了解如何实现自定义通用适配器知识的可以查看: 

下面可以看看效果图:

Android之ListView分页加载数据功能实现代码

标签:android,listView,分页,加载
0
投稿

猜你喜欢

  • mybatis 实体类字段大小写问题 字段获取不到值的解决

    2021-06-29 07:44:58
  • tcp socket客户端和服务端示例分享

    2021-10-22 13:24:17
  • C#开发WinForm之DataGridView开发详解

    2023-06-25 06:31:35
  • Android 动画之RotateAnimation应用详解

    2022-08-17 17:03:07
  • C#实现鼠标消息捕获

    2021-06-14 20:38:38
  • Android实现带圆环的圆形头像

    2021-09-30 09:04:47
  • 深入c# Func委托的详解

    2022-02-15 05:44:51
  • MPAndroidChart 自定义图表绘制使用实例

    2023-08-08 13:58:41
  • Android编程解析XML文件的方法详解【基于XmlPullParser】

    2022-09-21 22:48:40
  • 浅析Java Web错误/异常处理页面

    2022-02-14 00:13:50
  • Android仿微信发送语音消息的功能及示例代码

    2021-07-06 19:31:39
  • Android 类似UC浏览器的效果:向上滑动地址栏隐藏功能

    2023-01-29 05:01:41
  • Mybatis plus多租户方案的实战踩坑记录

    2023-08-01 05:19:09
  • Android自定义view Path 的高级用法之搜索按钮动画

    2023-12-23 06:53:28
  • C#实现json格式转换成对象并更换key的方法

    2021-12-23 00:09:39
  • Android 中Volley二次封装并实现网络请求缓存

    2023-09-17 06:16:35
  • 详谈Android编译命令

    2022-05-07 12:21:28
  • springboot操作静态资源文件的方法

    2022-07-13 06:29:11
  • Java基础之八大排序算法

    2022-02-05 12:35:47
  • 关于Java中的IO流总结(推荐)

    2023-08-23 18:13:56
  • asp之家 软件编程 m.aspxhome.com