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

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

  实现的原理:

  1. 首先要先确定默认展示在ListView上的数据,比如默认在ListView上展示10条数据。

  2. 将数据传递到自定义的适配器上,然后加载到ListView中。

  3. 当用户将数据拉到最后一条的时候,就要开始刷新加载新数据了。

  4. 通过监听ListView的滑动事件,判断是否达到最后一条,如果达到最后一条则开始刷新。

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

  整体结构如下:

  activity_main.xml

  <?xml version="1.0" encoding="utf-8"?>

  

  xmlns:tools="http://schemas.android.com/tools"

  android:layout_width="match_parent"

  android:layout_height="match_parent"

  tools:context="com.company.listviewdeepknow.MainActivity">

  

  android:id="@+id/mList"

  android:layout_width="match_parent"

  android:layout_height="match_parent">

  

  

  foot_boot.xml

  <?xml version="1.0" encoding="utf-8"?>

  

  android:layout_width="match_parent"

  android:layout_height="70dp"

  android:gravity="center"

  android:orientation="horizontal">

  

  android:id="@+id/progressBar"

  style="?android:attr/progressBarStyleSmall"

  android:layout_width="45dp"

  android:layout_height="45dp" />

  

  android:id="@+id/mLoad"

  android:layout_width="wrap_content"

  android:layout_height="wrap_content"

  android:text="加载更多..."

  android:textSize="20sp" />

  

  list_item.xml

  <?xml version="1.0" encoding="utf-8"?>

  

  android:layout_width="match_parent"

  android:layout_height="match_parent"

  android:orientation="horizontal">

  

  android:id="@+id/mTv1"

  android:layout_width="100dp"

  android:layout_height="100dp"

  android:textSize="20sp" />

  

  android:id="@+id/mTv2"

  android:layout_width="100dp"

  android:layout_height="100dp"

  android:layout_alignParentRight="true"

  android:textSize="20sp" />

  

  MainActivity.java

  public class MainActivity extends AppCompatActivity implements MyOnScrollListener.OnloadDataListener {

  //ListView展示的数据项

  private List 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 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 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 data;

  public MyOnScrollListener(View footer, List 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 data);

  }

  }

  MyAdapter.java

  public class MyAdapter extends MyBaseAdapter {

  public MyAdapter(List 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 extends BaseAdapter {

  protected List data;

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

  下面可以看看效果图:

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

  您可能感兴趣的文章: