简介

Android JectPack 组件中Paging 是其中一个重要组件。Paging 是对RecyclerVew.adpater的扩展。本文介绍其中一个知识点,用于记录自己的学习历程。

Adapter

RecyclerView是Android中的一个重要组件,使用RecyclerView组件最为重要的一个是自定义Adapter。如果使用Paging需要继承PagedListAdapter。一般自定义Adapter代码如下。

public class CheeseAdapter extends PagedListAdapter {    private static DiffUtil.ItemCallback diffCallBack = new DiffUtil.ItemCallback() {        @Override        public boolean areItemsTheSame(@NonNull Cheese oldItem, @NonNull Cheese newItem) {            return oldItem.getId() == newItem.getId();        }        @Override        public boolean areContentsTheSame(@NonNull Cheese oldItem, @NonNull Cheese newItem) {            return oldItem.getName().equals(newItem.getName());        }    };    public CheeseAdapter() {        super(diffCallBack);    }    @NonNull    @Override    public CheeseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {        return new CheeseViewHolder(parent);    }    @Override    public void onBindViewHolder(@NonNull CheeseViewHolder holder, int position) {        holder.bindTo(getItem(position));    }}

其中Cheese是自定义的显示item类,CheeseViewHolder是ViewHolder。

PagedListAdapter 简易类图

  1. PagedListAdapter 继承于RecyclerView.Adapter。表明这是一个RecyclerView.Adapter,并且扩展了RecyclerView.Adapter的功能。
  2. 扩展功能是支持异步差分更新功能。

装饰器模式

装饰器模式(Decorator Pattern),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰器模式比生成子类更灵活。 ----《大话设计模式》
标准的装饰器模式类图

  • 被装饰对象抽象接口(Component)
  • 具体的被装饰对象(ConcreteCompoent),负责接收装饰器。
  • Decorator装饰角色。持有一个抽象构件的引用。装饰对象接受所有客户端的请求,并把这些请求转发给真实的对象。这样,就能在真实对象调用前后增加新的功能
  • ConcreteDecorate具体装饰角色:负责给构件对象增加新的功能。

小结

可以通过装饰器模式对PagedListAdapter进行拆分理解,PagedListAdapter添加了异步差分更新内容。

更新流程

更新数据PagedList

PagedList 继承 AbstractList。说明这个是一个list。PagedList的功能参见源码的注释。
个人理解如下:

  1. pagedList 可以在多个线程进行传递和访问。
  2. 初始化之后,pagedList被UI主线程持有。

PagedList 初始化
Pagedlist 的初始化与DataSource 有关。当xxDataSource 重新isContiguous 为true是,初始化的是ContiguousPagedList。否则初始化为TiledPagedList。

更新具体流程

更新流程的接口调用关系是

  1. PagedListAdapter#submitList
  2. AsyncPagedListDiffer#submitList
  3. AdapterListUpdateCallback#onInserted 或者 onRemoved或者onMoved 或者onChanged
  4. RecyclerView.Adapter 的notifyItemxx通知接口

核心代码如下

public void submitList(@Nullable final PagedList pagedList,            @Nullable final Runnable commitCallback) {        if (pagedList != null) {// 判断submit 的pagedList 是否和 已持有的pagedList 是同类型的            if (mPagedList == null && mSnapshot == null) {                mIsContiguous = pagedList.isContiguous();            } else {                if (pagedList.isContiguous() != mIsContiguous) {                    throw new IllegalArgumentException("AsyncPagedListDiffer cannot handle both"                            + " contiguous and non-contiguous lists.");                }            }        }        // incrementing generation means any currently-running diffs are discarded when they finish        final int runGeneration = ++mMaxScheduledGeneration;        if (pagedList == mPagedList) {// submit 的 pagedList 和当前持有的 pagedList相同,不做任何操作直接返回            // nothing to do (Note - still had to inc generation, since may have ongoing work)            if (commitCallback != null) {                commitCallback.run();            }            return;        }        final PagedList previous = (mSnapshot != null) ? mSnapshot : mPagedList;        if (pagedList == null) {// submit 的 pagedList 为空,执行移除操作            int removedCount = getItemCount();            if (mPagedList != null) {                mPagedList.removeWeakCallback(mPagedListCallback);                mPagedList = null;            } else if (mSnapshot != null) {                mSnapshot = null;            }            // dispatch update callback after updating mPagedList/mSnapshot            mUpdateCallback.onRemoved(0, removedCount);            onCurrentListChanged(previous, null, commitCallback);            return;        }        if (mPagedList == null && mSnapshot == null) {// 为持有 pagedList  则将 submit 的pagedList 直接插入            // fast simple first insert            mPagedList = pagedList;            pagedList.addWeakCallback(null, mPagedListCallback);            // dispatch update callback after updating mPagedList/mSnapshot            mUpdateCallback.onInserted(0, pagedList.size());            onCurrentListChanged(null, pagedList, commitCallback);            return;        }        if (mPagedList != null) {            // first update scheduled on this list, so capture mPages as a snapshot, removing            // callbacks so we don't have resolve updates against a moving target            mPagedList.removeWeakCallback(mPagedListCallback);            mSnapshot = (PagedList) mPagedList.snapshot();            mPagedList = null;        }        if (mSnapshot == null || mPagedList != null) {            throw new IllegalStateException("must be in snapshot state to diff");        }        final PagedList oldSnapshot = mSnapshot;        final PagedList newSnapshot = (PagedList) pagedList.snapshot();        mConfig.getBackgroundThreadExecutor().execute(new Runnable() {            @Override            public void run() {                final DiffUtil.DiffResult result;                result = PagedStorageDiffHelper.computeDiff(                        oldSnapshot.mStorage,                        newSnapshot.mStorage,                        mConfig.getDiffCallback());                mMainThreadExecutor.execute(new Runnable() {                    @Override                    public void run() {                        if (mMaxScheduledGeneration == runGeneration) {                            latchPagedList(pagedList, newSnapshot, result,                                    oldSnapshot.mLastLoad, commitCallback);                        }                    }                });            }        });    }

更新流程如下:

  1. 如果submit的pagedList 为null ,则直接移除Adapter显示数据。
  2. 如果submit的pagedList不为null,且Adapter持有的padedList为null,则执行插入数据操作,通过Adapter更新UI界面。
  3. 如果submit的pagedList不为null,且Adapter持有的padedList不为null,则通过DiffUtil执行差分更新。

更多相关文章

  1. 类和 Json对象
  2. Andorid Dialog 示例【慢慢更新】
  3. Android中文API(144) —— JsonWriter
  4. Android(安卓)SDK Manager无法更新的解决
  5. Android热更新框架Tinker无法更新?
  6. Android之Handler用法总结
  7. android通过ksoap2对webservice的解析
  8. Android,一个思路实现APP版本更新
  9. Android(安卓)View的介绍和使用

随机推荐

  1. Android LGame入门
  2. Android中json操作数据的使用
  3. android闹钟(四):实现计时器
  4. Please use Android Tools > Fix Project
  5. 获取sdcard文件
  6. Android全屏设置方法
  7. Android Studio中Gradle编译配置
  8. Android常用mimetype类型
  9. android摄像头,linux摄像头设备,编程
  10. TextView和EditText