热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

Android代码实现AdapterViews和RecyclerView无限滚动

这篇文章主要为大家详细介绍了Android代码实现AdapterViews和RecyclerView无限滚动的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

应用的一个共同的特点就是当用户欢动时自动加载更多的内容,这是通过用户滑动触发一定的阈值时发送数据请求实现的。

相同的是:信息实现滑动的效果需要定义在列表中最后一个可见项,和某些类型的阈值以便于开始在最后一项到达之前开始抓取数据,实现无限的滚动。

实现无限滚动的现象的重要之处就在于在用户滑动到最低端之前就行数据的获取,所以需要加上一个阈值来帮助实现获取数据的预期。

使用ListView和GridView实现

每个AdapterView 例如ListView 和GridView 当用户开始进行滚动操作时候都会触发OnScrollListener .使用这个系统我们就可以定义一个基本的EndlessScrollListener ,通过创造继承OnScrollListener 的类来支持大多数情况下的使用。

package com.codepath.customadapter;

import android.widget.AbsListView;

/**
 * Created by Administrator on 2016/7/11.
 */
public abstract class EndlessScrollListener implements AbsListView.OnScrollListener {
 //在你滑动项下最少为多少时开始加载数据
 private int visibleThreshold = 5;
 //已经加载数据的当前页码
 private int currentPage = 0;
 //上一次加载数据后数据库的数据量
 private int previousTotalItemCount = 0;
 //我们是否在等待最后一组数据的加载
 private boolean loading = true;
 //设置开始页的下标
 private int startingPageIndex = 0;
 public EndlessScrollListener() {

 }
 public EndlessScrollListener(int visibleThreshold) {
 this.visibleThreshold = visibleThreshold;
 }
 public EndlessScrollListener(int visibleThreshold, int startingPageIndex) {
 this.visibleThreshold = visibleThreshold;
 this.startingPageIndex = startingPageIndex;
 }
 //这个方法可能会在滑动调用很多次,所以在设计时要保持谨慎
 //我们需要一些有用的参数来帮助我们,当我们需要加载更多数据的时候
 //但是我们首先要检查是否我们在等待先前的加载结束

//onScroll()当列表或网格视图被滚动后将会调用,参数一:报告状态的视图参数二:第一个可以看见的项的下标,参数三:可见项的数量参数四:listAdapter中所有的项数
 @Override
 public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

 //如果总项数为0,而且先前没有项,那么这个列表是无效的应该被设定为初始状态
 if (totalItemCount  previousTotalItemCount)) {
  loading = false;
  previousTotalItemCount = totalItemCount;
  currentPage++;
 }
 //如果当前没有加载,我们需要检查当前是否达到了阈值,如果是的话我们需要
 //加载更多的数据,执行onLoadMore
 if (!loading && (firstVisibleItem + visibleItemCount + visibleThreshold) >= totalItemCount) {
  loading = onLoadMore(currentPage + 1, totalItemCount);
 }
 }
 //定义实际加载数据的过程,如果数据加载完成返回false,如果正在加载返回true;
 public abstract boolean onLoadMore(int page, int totalItemCount);

 @Override
 public void onScrollStateChanged(AbsListView view, int scrollState) {
 //不采取动作
 }
}

要注意的是这是一个抽象的类,为了要使用这些,必须继承这个基本的类并且实现onLoadMore()方法实际的获取数据, 我们在一个活动中定义一个匿名的类来继承EndlessScrollListener然后将其连接AdapterView上

public class MainActivity extends Activity {
 @Override
 protected void onCreate(Bundle savedInstance) {
 //向平常一样
  ListView lvItems = (ListView) findViewById(R.id.lvItens);
  //将监听器绑定到上面
  lvItems.setOnScrollListener(new EndlessScrollListener() {
  @Override
  public boolean onLoadMore(int page, int totalItemsCount) {
  // 当新数据需要绑定到列表上的时候触发
  // 加载数据需要的代码Add whatever code is needed to append new items to your AdapterView
  customLoadMoreDataFromApi(page); 
  // or customLoadMoreDataFromApi(totalItemsCount); 
  return true; //数据加载中为true,不然为false; ONLY if more data is actually being loaded; false otherwise.
  }
 });
 }
 //加载更多的数据
 public void customLoadMoreDataFromApi(int offset) {
 //这个方法通常会发起一些网络请求,然后向适配器添加更多的数据
 //将偏移量数据作为参数附在请求里来获得一个数据的分页
 //解析API返回的值并且获得新的对象构建适配器
 }
}

现在当用户滑动并且触发阈值时会自动触发onloadMore() 方法,而且监听器给予了对于页数和数据总量的访问权限。

实现RecyclerView的无限滑动

我们可以使用相同的方法来定义一个接口EndlessRecyclerViewScrollListener 然后定义一个onLoadMore() 的方法来进行实现。由于LayoutManager负责项的生成和滑动的管理,我们需要一个LayoutManage的实例来收集必要的信息。
实现必要的分页需要这样的步骤:
1).直接复制EndlessRecyclerViewScrollListener.java
2).调用addOnScrollListener(...) 在RecyclerView 中来实现无限的分页,传递EndlessRecyclerViewScrollListener的实例来实现onLoadMore 方法来决定什么时候来加载新的数据
3).在onLoadMore 方法中通过发送网络请求或者从源数据加载来获得更多item。

 protected void onCreate(Bundle savedInstanceState) {
 // Configure the RecyclerView获得RecylerView的实例
 RecyclerView rvItems = (RecyclerView) findViewById(R.id.rvContacts);
 LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
 recyclerView.setLayoutManager(linearLayoutManager);
 // Add the scroll listener
 rvItems.addOnScrollListener(new EndlessRecyclerViewScrollListener(linearLayoutManager) {
  @Override
  public void onLoadMore(int page, int totalItemsCount) {
  // Triggered only when new data needs to be appended to the list
  // Add whatever code is needed to append new items to the bottom of the list
  customLoadMoreDataFromApi(page); 
  }
 });
 }

 // Append more data into the adapter
 // This method probably sends out a network request and appends new data items to your adapter. 
 public void customLoadMoreDataFromApi(int page) {
 // Send an API request to retrieve appropriate data using the offset value as a parameter.
 // --> Deserialize API response and then construct new objects to append to the adapter
 // --> Notify the adapter of the changes
 }
}

EndlessRecyclerView

public abstract class EndlessRecyclerViewScrollListener extends RecyclerView.OnScrollListener {
 // The minimum amount of items to have below your current scroll position
 // before loading more.
 private int visibleThreshold = 5;
 // The current offset index of data you have loaded
 private int currentPage = 0;
 // The total number of items in the dataset after the last load
 private int previousTotalItemCount = 0;
 // True if we are still waiting for the last set of data to load.
 private boolean loading = true;
 // Sets the starting page index
 private int startingPageIndex = 0;

 RecyclerView.LayoutManager mLayoutManager;

 public EndlessRecyclerViewScrollListener(LinearLayoutManager layoutManager) {
 this.mLayoutManager = layoutManager;
 }

 public EndlessRecyclerViewScrollListener(GridLayoutManager layoutManager) {
 this.mLayoutManager = layoutManager;
 visibleThreshold = visibleThreshold * layoutManager.getSpanCount();
 }

 public EndlessRecyclerViewScrollListener(StaggeredGridLayoutManager layoutManager) {
 this.mLayoutManager = layoutManager;
 visibleThreshold = visibleThreshold * layoutManager.getSpanCount();
 }

 public int getLastVisibleItem(int[] lastVisibleItemPositions) {
 int maxSize = 0;
 for (int i = 0; i  maxSize) {
  maxSize = lastVisibleItemPositions[i];
  }
 }
 return maxSize;
 }

 // This happens many times a second during a scroll, so be wary of the code you place here.
 // We are given a few useful parameters to help us work out if we need to load some more data,
 // but first we check if we are waiting for the previous load to finish.
 @Override
 public void onScrolled(RecyclerView view, int dx, int dy) {
 int lastVisibleItemPosition = 0;
 int totalItemCount = mLayoutManager.getItemCount();

 if (mLayoutManager instanceof StaggeredGridLayoutManager) {
  int[] lastVisibleItemPositiOns= ((StaggeredGridLayoutManager) mLayoutManager).findLastVisibleItemPositions(null);
  // get maximum element within the list
  lastVisibleItemPosition = getLastVisibleItem(lastVisibleItemPositions);
 } else if (mLayoutManager instanceof LinearLayoutManager) {
  lastVisibleItemPosition = ((LinearLayoutManager) mLayoutManager).findLastVisibleItemPosition();
 } else if (mLayoutManager instanceof GridLayoutManager) {
  lastVisibleItemPosition = ((GridLayoutManager) mLayoutManager).findLastVisibleItemPosition();
 }

 // If the total item count is zero and the previous isn't, assume the
 // list is invalidated and should be reset back to initial state
 if (totalItemCount  previousTotalItemCount)) {
  loading = false;
  previousTotalItemCount = totalItemCount;
 }

 // If it isn't currently loading, we check to see if we have breached
 // the visibleThreshold and need to reload more data.
 // If we do need to reload some more data, we execute onLoadMore to fetch the data.
 // threshold should reflect how many total columns there are too
 if (!loading && (lastVisibleItemPosition + visibleThreshold) > totalItemCount) {
  currentPage++;
  onLoadMore(currentPage, totalItemCount);
  loading = true;
 }
 }

 // Defines the process for actually loading more data based on page
 public abstract void onLoadMore(int page, int totalItemsCount);

}

注意问题:
 1.对于ListView,确定将绑定监听器的步骤放在onCreate()的方法中
 2.为可加可靠的进行分页,需要确定在向列表中添加新数据的时候先清理适配器中的数据
对于RecyclerView来说在通知适配器时推荐更细致的更新。
 3.对于RecyclerView来说确保在清除列表中的数据的时候迅速的通知适配器内容更新了,以便于可以触发新的onScroll事件,重置自己 

展示进度条

为了在底部展示进度条证明ListView正在加载。我们可以在Adapter中进行设置,我们可以定义两类,可以是进度条类型或者是文本表明达到了最底行,参考:http://guides.codepath.com/android/Endless-Scrolling-with-AdapterViews-and-RecyclerView

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


推荐阅读
  • 本文介绍了一种支付平台异步风控系统的架构模型,旨在为开发类似系统的工程师提供参考。 ... [详细]
  • 使用 Git Rebase -i 合并多个提交
    在开发过程中,频繁的小改动往往会生成多个提交记录。为了保持代码仓库的整洁,我们可以使用 git rebase -i 命令将多个提交合并成一个。 ... [详细]
  • 本文详细介绍了Linux系统中用于管理IPC(Inter-Process Communication)资源的两个重要命令:ipcs和ipcrm。通过这些命令,用户可以查看和删除系统中的消息队列、共享内存和信号量。 ... [详细]
  • 一个建表一个执行crud操作建表代码importandroid.content.Context;importandroid.database.sqlite.SQLiteDat ... [详细]
  • A*算法在AI路径规划中的应用
    路径规划算法用于在地图上找到从起点到终点的最佳路径,特别是在存在障碍物的情况下。A*算法是一种高效且广泛使用的路径规划算法,适用于静态和动态环境。 ... [详细]
  • NX二次开发:UFUN点收集器UF_UI_select_point_collection详解
    本文介绍了如何在NX中使用UFUN库进行点收集器的二次开发,包括必要的头文件包含、初始化和选择点集合的具体实现。 ... [详细]
  • 解决SQL Server数据库sa登录名无法连接的问题
    在安装SQL Server数据库后,使用Windows身份验证成功,但使用SQL Server身份验证时遇到问题。本文将介绍如何通过设置sa登录名的密码、启用登录名状态以及开启TCP协议来解决这一问题。 ... [详细]
  • MySQL 数据库连接方法
    本文介绍了如何使用 MySQL 命令行工具连接到指定的数据库。 ... [详细]
  • 在 Mac 上配置 NDK
    本文详细介绍了如何在 Mac 上配置 Android NDK,包括设置环境变量和解决常见问题的方法。 ... [详细]
  • 如何解决8080端口被占用问题
    本文介绍了如何通过命令行和任务管理器查找并终止占用8080端口的进程,以确保该端口能够正常使用。 ... [详细]
  • Excel 数据分析基础
    Excel 是数据分析中最基本且强大的工具之一,具备多种实用功能和操作方法。本文将简要介绍 Excel 的不同版本及其兼容性问题,并探讨在处理大数据时的替代方案。 ... [详细]
  • 本文介绍了如何在 ASP.NET 中设置 Excel 单元格格式为文本,获取多个单元格区域并作为表头,以及进行单元格合并、赋值、格式设置等操作。 ... [详细]
  • LDAP服务器配置与管理
    本文介绍如何通过安装和配置SSSD服务来统一管理用户账户信息,并实现其他系统的登录调用。通过图形化交互界面配置LDAP服务器,确保用户账户信息的集中管理和安全访问。 ... [详细]
  • Android 自定义 RecycleView 左滑上下分层示例代码
    为了满足项目需求,需要在多个场景中实现左滑删除功能,并且后续可能在列表项中增加其他功能。虽然网络上有很多左滑删除的示例,但大多数封装不够完善。因此,我们尝试自己封装一个更加灵活和通用的解决方案。 ... [详细]
  • 如果应用程序经常播放密集、急促而又短暂的音效(如游戏音效)那么使用MediaPlayer显得有些不太适合了。因为MediaPlayer存在如下缺点:1)延时时间较长,且资源占用率高 ... [详细]
author-avatar
yuguiping123
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有