Android-Paging源码分析

Paging架构

再回头看一眼Paging的架构图

v2-ff67e37ea6c8fa81028308225462891e_b.jpg

可以看到Paing的核心是PagedList,这个PagedList携带着一个DataSource,也即产生数据的工厂,PagedList中还有分页的配置,例如每页多少个数据,距离底部多少个数据时开始自动加载下一页数据,以及设置加载与更新UI的线程等。

从触发机制与数据流向角度看,构建PagedList是在页面初始化或者下拉刷新时,使用PagedList.Builder,传入PagedList.Config和DataSource.Factory两个对象。构造出来的PagedList对象调用Adapter.submitList方法传给Adapter,Adapter中持有传入的PagedList对象。submitList还会触发DataSource的loadInitial方法来初始化数据,其实这里初始化数据有两种形式,可以先把数据准备好再调用submitList,在loadInitial方法中直接将数据喂给callback即可,或者还可以在loadInitial方法中触发数据请求,在请求结果回调中调用callback将数据传给Adapter,这些就是触发数据加载的两种逻辑。

从上图中即可看出数据流向的逻辑,数据从DataSource中生产出来,不管是loadInitial还是loadAfter又或者是loadBefore,都是使用callback调用onResult将数据回传。


构造PagedList

v2-20fd69fd1d2d085ebf7f4e17068b38e5_b.jpg

首先来看看PagedList的类结构,其内部有BoundaryCallback、Builder、Callback、Config四个内部类。一个一个来看具体定义

首先是BoundaryCallback,

@MainThread
    public abstract static class BoundaryCallback<T> {
     

        public void onZeroItemsLoaded() {}

        public void onItemAtFrontLoaded(@NonNull T itemAtFront) {}

        public void onItemAtEndLoaded(@NonNull T itemAtEnd) {}
    }

把注释都删掉只下定义了3个方法,看这个类的注释,意思大概是如果将本地缓存数据当作网络数据的缓存时,用本地数据构造了一个PagedList并更新到UI上时,这时还是需要通知一下触发一下网络请求的。也就是说我们可以在将数据传给Adapter更新UI的同时异步加载网络数据,并将网络数据储存到本地,而DataSource每次只需要从本地取数据即可,而这个BoundaryCallback就是用来通知触发异步加载网络数据的。

根据调用堆栈,可发现这个onZeroItemsLoaded是在DataSource的callback.onResult中调用,且callback传回来的数据为空。下面两个方法onItemAtFrontLoaded和onItemAtEndLoaded则分别是在PagedList滑动到可自动加载下一页数据时触发。当DataSource中callback传回数据时,发现当前PagedList数据不为空,而请求传回的数据为空时,这也会被当作是可加载下一页数据。总结一下,BoundaryCallback的三个方法是在自动触发加载下一页数据时回调的,或者是当前PagedList数据不为空,也就是Adapter有内容,而新加载的数据为空时调用。从感性上来说,这个BoundaryCallback应该是一个数据加载监听的辅助接口,用于在加载数据时再异步辅助加载更多数据。

再看看这个PagedList.Builder类,这纯粹就是个Build模式类,仅仅是为了传入一个参数从而构造出一个PagedList对象。查看其build方法,限制了NotifyExecutor和FetchExecutor不能为null,最后调用了PageList.create方法,将set的参数传入,返回一个PagedList对象。在PagedList.create方法中,有两个分支,分别创建的是ContiguousPagedList和TitledPagedList。判断是dataSource.isContiguous,这个返回值表示两页之间是不是承接式的,也即两页之间的关系是不是当前页和上一页下一页这样的有关系,这样返回的是ContiguousPagedList对象,否则返回TiledPagedList对象,tiled表示是不是平铺的,也即每个Item之间确定关系,是根据item的位置关系来加载更多数据的。

再来看PagedList.Config类,这个类结构较为简单,只定义了几个字段外加一个Builder

public static class Config {
     
        @SuppressWarnings("WeakerAccess")
        public static final int MAX_SIZE_UNBOUNDED = Integer.MAX_VALUE;

        public final int pageSize;

        @SuppressWarnings("WeakerAccess")
        public final int prefetchDistance;

        @SuppressWarnings("WeakerAccess")
        public final boolean enablePlaceholders;

        public final int maxSize;

pageSize表示每页的item数量,prefetchDistance表示距离底部或顶部还差多少个item就开始触发loadAfter和loadBefore,enablePlaceHolder表示是否支持展示null placeholders,maxSize表示这个pageList的最大容量。

PagedList还有一个Callback的内部类

public abstract static class Callback {
     
        public abstract void onChanged(int position, int count);

        public abstract void onInserted(int position, int count);

        @SuppressWarnings("unused")
        public abstract void onRemoved(int position, int count);
    }

只有三个方法,分别表示PagedList中的数据发生了变化、插入了数据,移除了数据。这个Callback接口只是为了监听PagedList的数据变化,AsyncPagedListDiffer对其的实现是mPagedListCallback对象,在相应的实现方法中直接调用了mUpdateCallback的相应方法,这个mUpdateCallback是AdapterListUpdateCallback类型的。在AdapterListUpdateCallback中的相应方法中,就调用了RecyclerView.Adapter的相应局部刷新api。

public final class AdapterListUpdateCallback implements ListUpdateCallback {
     
    @NonNull
    private final RecyclerView.Adapter mAdapter;

    public AdapterListUpdateCallback(@NonNull RecyclerView.Adapter adapter) {
     
        mAdapter = adapter;
    }

    @Override
    public void onInserted(int position, int count) {
     
        mAdapter.notifyItemRangeInserted(position, count);
    }

    @Override
    public void onRemoved(int position, int count) {
     
        mAdapter.notifyItemRangeRemoved(position, count);
    }

    @Override
    public void onMoved(int fromPosition, int toPosition) {
     
        mAdapter.notifyItemMoved(fromPosition, toPosition);
    }

    @Override
    public void onChanged(int position, int count, Object payload) 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值