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

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

下面可以看看效果图:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android程序开发之Listview下拉刷新上拉(滑动分页)加载更多

    最近做的类似于微博的项目中,有个Android功能要使用到listview的向下拉刷新来刷新最新消息,向上拉刷新(滑动分页)来加载更多. 新浪微博就是使用这种方式的典型. 当用户从网络上读取微博的时候,如果一下子全部加载用户未读的微博这将耗费比较长的时间,造成不好的用户体验,同时一屏的内容也不足以显示如此多的内容.这时候,我们就需要用到另一个功能,那就是listview的分页了,其实这个分页可以做成客户端的分页,也可以做成服务器端的分页(点击加载时,从服务器对应的加载第N页就好了!!!).通过分

  • android实现listview分页的方法

    本文实例讲述了android实现listview分页的方法.分享给大家供大家参考.具体分析如下: 最近做了下listview的分页,跟WEB上的分页是一个意思,需要那几个分页参数,不同的是sqlite中分页的查询语句,简便的方法需要用Limit,Offset关键字,前者是查询每页展示的记录数,后者是越过多少记录数,说得明白点就是忽略前面多少行记录之后,取多少行记录 我分页采用了一个重要的类Page,通过封装Page类,做为参数传递进来,返回出去也是个Page对象 import java.util

  • Android实现基于滑动的SQLite数据分页加载技术(附demo源码下载)

    本文实例讲述了Android实现基于滑动的SQLite数据分页加载技术.分享给大家供大家参考,具体如下: main.xml如下: <menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/action_settings" android:orderInCategory="100" android:showAs

  • Android提高之SQLite分页读取实现方法

    一般来说,Android自身就包含了常用于嵌入式系统的SQLite,这样就免去了开发者自己移植安装的功夫.SQLite 支持多数SQL92标准,很多常用的SQL命令都能在SQLite上面使用,除此之外Android还提供了一系列自定义的方法去简化对SQLite数据库的操作.不过有跨平台需求的程序还是建议使用标准的SQL语句,毕竟这样容易在多个平台之间进行移植. 先来贴出本文程序运行的结果图: 本文实例程序主要讲解了SQLite的基本用法,如:创建数据库,使用SQL命令查询数据表.插入数据,关闭数

  • Android实现ListView分页自动加载数据的方法

    Android应用开发中,采用ListView组件来展示数据是很常用的功能,当一个应用要展现很多的数据时,一般情况下都不会把所有的数据一次就展示出来,而是通过分页的形式来展示数据,个人觉得这样会有更好的用户体验.因此,很多应用都是采用分批次加载的形式来获取用户所需的数据.例如:微博客户端可能会在用户滑动至列表底端时自动加载下一页数据,也可能在底部放置一个"查看更多"按钮,用户点击后,加载下一页数据. 下面通过一个Demo来展示ListView功能如何实现:该Demo通过在ListVie

  • Android开发中滑动分页功能实例详解

    本文实例讲述了Android开发中滑动分页功能.分享给大家供大家参考,具体如下: android UI 往右滑动,滑动到最后一页就自动加载数据并显示 如图: Java代码: package cn.anycall.ju; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import android.app.Activity; import andro

  • Android中实现多行、水平滚动的分页的Gridview实例源码

    功能要求: (1)比如每页显示2X2,总共2XN,每个item显示图片+文字(点击有链接). 如果单行水平滚动,可以用Horizontalscrollview实现. 如果是多行水平滚动,则结合Gridview(一般是垂直滚动的)和Horizontalscrollview实现. (2)水平滚动翻页,下面有显示当前页的icon. 1.实现自定义的HorizontalScrollView(HorizontalScrollView.java): 因为要翻页时需要传当前页给调用者,所以fling函数中自己

  • Android实现简单的分页效果

    本文实例为大家分享了Android分页效果的具体代码,供大家参考,具体内容如下 1.实现分页最主要的就是封装分页代码,然后在按钮里实现相关的操作 /** * 分页工具 * * @Project App_Page * @Package com.android.dividepage * @author chenlin * @version 1.0 * @Date 2012年6月2日 * @Note TODO * @param <T> */ public class PageHelper<T&

  • Android App中使用ViewPager实现滑动分页的要点解析

    以前如果要做 Tab 分页的话,必须要用一个很难用的 TabActivity,而且做出来的效果很差,弹性也很小 忘了从什么时候开始,Google release 了 ViewPager 这好东西取代了以前难用的 Gallery 元件,加上从 Honeycomb 导入的 Fragment 之后终于能够简单做出好看又好用的 Layout 了! 这里我们采用PagerTabStrip ,做出来的效果如下 特色就是使用简单,出来的效果则是目前显示的分页 Tab 的文字会自动置中,然后分别在左右显示上一个

  • Android ListView分页功能实现方法

    通过本次小Demo我学到了: 1.ListView的小小的一个分页功能 2.加深了对自定义控件的理解 3.对ListView的优化 4.对BaseAdapter的使用 5.自定义Adapter 6.接口的回调 要实现下面的效果--当拖动ListView到底部的时候,显示一个ProgressBar和一个"正在加载..."的TextView.并且过两秒钟后,在下面加载出新的数据.项目的目录结构和程序要实现的效果如下:   首先是布局部分: 我为了实现此效果,首先在布局文件中新建了一个foo

  • Android滑动动态分页实现方法

    本文实例讲述了Android滑动动态分页实现方法.分享给大家供大家参考,具体如下: 实现 Android.widget.AbsListView.OnScrollListener 主要代码: private int lastItemIndex; @Override public void onScroll(AbsListView v, int firstVisibleItem,int visibleItemCount, int totalItemCount) { lastItemIndex = f

随机推荐