简介
在2018年5月9日的谷歌开发者大会(Google I/O 2018) 中提出在去年发布的广受欢迎的架构组件上,进一步改进并推出了Jetpack。Jetpack能帮助我们更专注提升应用体验,加快应用开发速度,处理类似后台任务、UI 导航以及生命周期管理等。
发布的新版 Android Jetpack 组件中更新的内容包括 4 个部分:WorkManager、Paging、Navigation 以及 Slices。
我们今天要说的就是Paging,在进行大数据查询的时候,Paging分页组件可以让我们从本地或者网络中通过渐进的方式、逐步的请求数据加载,在不过多增加设备负担或等待时间的情况下,让应用拥有了处理大型数据的能力,其中包括对RecycleView的支持。
会从以下几个方面去介绍:
- paging的整体流程
- paging主要类的功能
- 如何使用paging
为什么使用paging,或者paging的优点
在一个新技术出来的时候,我们不能盲目的去使用,不能为了使用而使用,引入新技术是有一定的成本的。所以在真正的工作项目中引入一个新技术,前期一定要调研好,要明确引入后,利大于弊,才能着手去做。
回归正题,我大概总结以下几点:
- 业务和UI高度分离,更加灵活
- 引入LiveData,具有了生命周期
- 线程切换,数据处理在子线程,显示在UI线程
- 封装了实现,对于应用来说更加方便
paging整体流程

上图是非常棒的官方原理图,通过原理图,能很清晰的看到数据的传输过程,已经设计到的线程变动。
- DataSource 在IO线程中获取数据,数据可以是本地数据库或者网络请求返回
- DataSource将数据通过主线程线程传递给PagedList
- pagedList然后将数据传递给DiffUtil
- DiffUtil在对比现在的item和新建item的差异,这个过程是在异步线程中进行的
- 对比结束,通过PagedListAdapter调用notifyItemInserted()将新的数据插入到适当的位置
- RecycleView收到通知后会更新视图。
paging几个主要类的功能
DataSource
数据源,数据的改变会驱动列表的更新。
Datasource提供了三种实现的类:
PageKeyedDataSource:下一次的请求依赖于上一次的某个值,例如:在平时的分页接口中,loadmore时,需要上一次接口返回的cursor值作为这次的参数进行请求。ItemKeyedDataSource:下一条的数据依赖于上一条的数据。PositionalDataSource:请求从具体位置开始,例如:我要请求从第20个数据开始的列表。
根据使用场景选择实现DataSource不同的抽象类,使用时需要实现请求加载数据的方法。其中这三种都需要实现loadInitial()方法,个字都封装了请求初始化数据的参数类型LoadInitialParams。不同是分享加载数据的方法,PageKeyedDataSource和ItemKeyedDataSrouce比较相似,需要实现loadBefore()和loadAfter()方法,同样对请求参数做了封装,即LoadParams。PositionalDataSource需要实现loadRange()
PagedList
核心类,它从数据源取出数据,同时,它负责控制 第一次默认加载多少数据,之后每一次加载多少数据,如何加载等等,并将数据的变更反映到UI上。
Config:配置PagedList从Datasource加载数据的方式,其中包含以下属性
PagedList.Config build = new PagedList.Config.Builder()
.setEnablePlaceholders(true) // 数据为null时是否使用占位符
.setPrefetchDistance(pageSize) // 当距离底部多少个数据时,开始加载数据
.setInitialLoadSizeHint(pageSize * 2) // 第一次加载时的数量
.setPageSize(pageSize) // 每一次加载的数量
.build();
PagedListAdapter
适配器,RecyclerView的适配器,通过DiffUtil来分析数据的变化,然后通过相应的方法刷新UI(增加/删除/替换等)
PagedListAdapter是很简单,仅仅是一个被代理的对象,所有的相关逻辑都委托了给AsyncPagedListDiffer
public abstract class PagedListAdapter<T, VH extends RecyclerView.ViewHolder>
extends RecyclerView.Adapter<VH> {
private final AsyncPagedListDiffer<T> mDiffer;
private final AsyncPagedListDiffer.PagedListListener<T> mListener =
new AsyncPagedListDiffer.PagedListListener<T>() {
@Override
public void onCurrentListChanged(@Nullable PagedList<T> currentList) {
PagedListAdapter.this.onCurrentListChanged(currentList);
}
};
protected PagedListAdapter(@NonNull DiffUtil.ItemCallback<T> diffCallback) {
mDiffer = new AsyncPagedListDiffer<>(this, diffCallback);
mDiffer.mListener = mListener;
}
@SuppressWarnings("unused, WeakerAccess")
protected PagedListAdapter(@NonNull AsyncDifferConfig<T> config) {
mDiffer = new AsyncPagedListDiffer<>(new AdapterListUpdateCallback(this), config);
mDiffer.mListener = mListener;
}
public void submitList(PagedList<T> pagedList) {
mDiffer.submitList(pagedList);
}
@Nullable
protected T getItem(int position) {
return mDiffer.getItem(position);
}
@Override
public int getItemCount() {
return mDiffer.getItemCount();
}
@Nullable
public PagedList<T> getCurrentList() {
return mDiffer.getCurrentList();
}
@SuppressWarnings("WeakerAccess")
public void onCurrentListChanged(@Nullable PagedList

本文深入解析了Android Jetpack中的Paging组件,详细介绍了其工作原理、主要类的功能及使用方法,帮助开发者理解如何高效地处理大数据量的分页加载。
最低0.47元/天 解锁文章
539





