Jetpack插件化学习之AndroidX Paging 大数据列表加载库二--使用

Jetpack插件化学习之AndroidX Paging 大数据列表加载库二–使用

上一篇主要介绍了Paging加载库的主要组件,以及组件之间的工作方式,不是很清楚的可以移步上一篇
Jetpack插件化学习之AndroidX Paging 大数据列表加载库一

本篇主要介绍Paging库如何在项目中使用。
开篇之前,本文的数据来源以及demo代码的书写参考了这位大佬的文章。
使用Paging Library获取网络数据
本篇也是直接加载的网络数据。

首先在项目中添加Paging库依赖

    // androidx  paging
    implementation "androidx.lifecycle:lifecycle-extensions:2.0.0"
    annotationProcessor "androidx.lifecycle:lifecycle-compiler:2.0.0"
    implementation "androidx.paging:paging-runtime:2.1.0-alpha01"

依赖中看到有AndoridX的依赖。关于AndoridX的介绍以及Android到AndroidX的升级

接下来按照Paging的组件,依次创建

  1. DataSource
  2. PagedList&LivePagedListProvider

DataSource

初始化一个PositionalDataSource对象并实现相关方法。loadInitialloadRange


public class PagingItemDataViewModel extends AndroidViewModel {

    public static final int CONTENT_LENGTH = 20;
    public static final int FIRST_PAGE = 1;
    private int mPage = FIRST_PAGE;

//    final List resultBeans = new ArrayList<>();

    private LiveData> mLiveData;

    public PagingItemDataViewModel(@NonNull Application application) {
        super(application);

    }

    public LiveData> getmLiveData() {
        initPageList();
        return mLiveData;
    }

    private void initPageList() {

        final PositionalDataSource positionalDataSource = new PositionalDataSource() {
            private int computeCount() {
                //这里的实际计数代码
                return CONTENT_LENGTH;
            }

            /**
             * 网络请求耗时操作
             * @param onHttpRequestListener 网络请求成功的回调
             * @param page 加载到第几页
             */
            private void loadRangeInternal(final OnHttpRequestListener onHttpRequestListener, int page) {
                //这里的实际加载代码
                ManageHttp.getWelfare1(new BaseOnResponseCallBack>(List.class) {

                    @Override
                    public void onNext(List data, int IDUrl, boolean isCache) {
                        onHttpRequestListener.onNext(data, IDUrl, isCache);
                    }

                    @Override
                    public void onStart(int IDUrl, boolean isCache) {

                    }

                    @Override
                    public void onCompleted(int IDUrl, boolean isCache) {

                    }

                    @Override
                    public void onError(Throwable e, int IDUrl, boolean isCache) {

                    }
                }, page);
//                return resultBeans;
            }

            @Override
            public void loadInitial(@NonNull LoadInitialParams params, @NonNull final LoadInitialCallback callback) {
                // 计算一页显示的条目
                final int totalCount = computeCount();
                // 计算显示到第几条数据
                final int position = computeInitialLoadPosition(params, totalCount);
                final int loadSize = computeInitialLoadSize(params, position, totalCount);
                //初次初始化
                loadRangeInternal(new OnHttpRequestListener() {
                    @Override
                    public void onStart(int IDUrl, boolean isCache) {

                    }

                    @Override
                    public void onNext(Object data, int IDUrl, boolean isCache) {
//                        resultBeans.addAll((Collection) data);
                        gankData = (List) data;
                        callback.onResult((List) data, position, totalCount);
                    }

                    @Override
                    public void onCompleted(int IDUrl, boolean isCache) {

                    }

                    @Override
                    public void onError(Throwable e, int IDUrl, boolean isCache) {

                    }
                }, mPage);

            }

            List gankData = new ArrayList<>();

            @Override
            public void loadRange(@NonNull LoadRangeParams params, @NonNull final LoadRangeCallback callback) {
                LogUtils.d("PagingItemDataViewModel", "loadRange", "params->=" + params.loadSize, "params->=" + params.startPosition);
                // 每次加载到翻页条目,page增量
                mPage++;
                loadRangeInternal(new OnHttpRequestListener() {
                    @Override
                    public void onStart(int IDUrl, boolean isCache) {

                    }

                    @Override
                    public void onNext(Object data, int IDUrl, boolean isCache) {
//                        resultBeans.addAll((Collection) data);
                        gankData = (List) data;
                        // 回调到provider中
                        callback.onResult((List) data);
                    }

                    @Override
                    public void onCompleted(int IDUrl, boolean isCache) {

                    }

                    @Override
                    public void onError(Throwable e, int IDUrl, boolean isCache) {

                    }
                }, mPage);
            }

        };
        // 构建LiveData
        mLiveData = new LivePagedListBuilder(new PageDataSourceFactory(positionalDataSource)
                , new PagedList.Config.Builder().setPageSize(CONTENT_LENGTH)
                .setPrefetchDistance(CONTENT_LENGTH)
                .setEnablePlaceholders(false).setInitialLoadSizeHint(CONTENT_LENGTH)
                .build()).build();
    }
}

为了使项目的结构更加清晰,将此处的业务逻辑放到ViewModel层。

computeCount:方法用来初始化每一页所展示的数据。

   private int computeCount() {
                //这里的实际计数代码
                return CONTENT_LENGTH;
            }

loadRangeInternal:从网络加载数据的方法。
第一个参数onHttpRequestListener网络请求成功的回调接口,page为加载到第几页。

private void loadRangeInternal(final OnHttpRequestListener onHttpRequestListener, int page) ;
****

loadInitial:进行第一次页面加载时候的数据加载。

// 计算一页显示的条目
 final int totalCount = computeCount();
// 计算显示到第几条数据
final int position = computeInitialLoadPosition(params, totalCount);
final int loadSize = computeInitialLoadSize(params, position, totalCount);

第一次数据加载完成之后,要把上述的几个变量回调出去,通知当前加载的数据条目数,以及每一页需要加载的条目数。

callback.onResult((List) data, position, totalCount);

loadRange:滑动列表时候触发数据的请求,并将数据回调出去。

  public void loadRange(@NonNull LoadRangeParams params, @NonNull final LoadRangeCallback callback) 

LoadRangeParams :包含当前加载的位置position、下一页加载的长度count

LoadRangeCallback:将数据回调给界面使用callback.onResult

PagedList&LivePagedListProvider

LivePagedListProvider通过构造方法将PagedList与DataSource联系在一起。

  mLiveData = new LivePagedListBuilder(new PageDataSourceFactory(positionalDataSource)
                , new PagedList.Config.Builder().setPageSize(CONTENT_LENGTH)
                .setPrefetchDistance(CONTENT_LENGTH)
                .setEnablePlaceholders(false).setInitialLoadSizeHint(CONTENT_LENGTH)
                .build()).build();

mLiveData是一个实现了观察者模式的对象。使用该对象post的方法可以将获取的数据返回到UI层,供RecycleView展示。

使用到的DataSource创建类

public class PageDataSourceFactory extends DataSource.Factory {

    public PositionalDataSource mPositionalDataSource;
    public PageDataSourceFactory(PositionalDataSource positionalDataSource) {
        this.mPositionalDataSource   =positionalDataSource;
    }

    @Override
    public DataSource create() {
        return mPositionalDataSource;
    }
}

至此,我们完成了数据的分页逻辑已经完成。回头来看一下里面的代码,主要有loadInitial、loadRange这两个方法。以及初始化LiveData的过程。

接下来,我们看一下在Activity中如何获取数据。


class PagingActivity : BaseMvpActivity(), Contract.IView {
    override fun initTitle() {

    }

    var adapter: MyAdapter? = null
    var pagingItemDataViewModel: PagingItemDataViewModel? = null
    override val layoutViewID: Int
        get() = R.layout.activity_main_paging


    override fun initPresenter(): MainPresenter {
        return MainPresenter()
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        pagingItemDataViewModel = ViewModelProviders.of(this).get(PagingItemDataViewModel::class.java)

        adapter = MyAdapter(object : DiffUtil.ItemCallback() {
            override fun areItemsTheSame(oldItem: GankData, newItem: GankData): Boolean {
                return oldItem._id.equals(newItem._id)
            }

            override fun areContentsTheSame(oldItem: GankData, newItem: GankData): Boolean {
                return oldItem.url.equals(newItem.url)
            }

        })
        recyclerView.layoutManager = LinearLayoutManager(this)
        recyclerView.adapter = adapter
        pagingItemDataViewModel!!.getmLiveData().observe(this, object : Observer> {
            override fun onChanged(t: PagedList?) {
                adapter!!.submitList(t)
            }

        })
    }

    override fun onViewClick(v: View) {
        super.onViewClick(v)
    }
}

Activity界面中我们只需要关注RecycleView的Adapter的生成。

Adapter

在上一篇的初识中RecycleView的Adapter需要继承自Paging的PagedListAdapter


public class MyAdapter extends PagedListAdapter {
    private Context mContext;

    protected MyAdapter(@NonNull DiffUtil.ItemCallback diffCallback) {
        super(diffCallback);
    }


    @NonNull
    @Override
    public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        mContext = parent.getContext();
        return new BaseViewHolder(LayoutInflater.from(mContext).inflate(R.layout.item_main, parent, false));
    }

    @Override
    public void onBindViewHolder(@NonNull BaseViewHolder holder, int position) {
        TextView tvName = holder.getView(R.id.tv_name);
        ImageView imageView = holder.getView(R.id.iv);

        GankData data = getItem(position);
        tvName.setText(position+"");
         GlideUtils.loadImage(mContext,imageView,data.getUrl());

    }
}

继承PagedListAdapter,添加构造方法。
可以看到在构造方法中添加以往没有见到的DiffUtil.ItemCallback

 protected MyAdapter(@NonNull DiffUtil.ItemCallback diffCallback) {
        super(diffCallback);
    }

该callback用来判断接收的数据是否为同一个数据

BaseViewHolder相关

public class BaseViewHolder extends RecyclerView.ViewHolder {
    private final SparseArray viewSparseArray;

    public BaseViewHolder(@NonNull View itemView) {
        super(itemView);
        viewSparseArray = new SparseArray<>();
    }

    public  T getView(@IdRes int id) {
        View view = viewSparseArray.get(id);
        if (null == view) {
            view = itemView.findViewById(id);
            viewSparseArray.put(id, view);
        }
        return (T) view;
    }
}

在Activity中实现DiffUti.ItemCall

adapter = MyAdapter(object : DiffUtil.ItemCallback() {
            override fun areItemsTheSame(oldItem: GankData, newItem: GankData): Boolean {
                return oldItem._id.equals(newItem._id)
            }

            override fun areContentsTheSame(oldItem: GankData, newItem: GankData): Boolean {
                return oldItem.url.equals(newItem.url)
            }

        })

在areItemsTheSame、areContentsTheSame中编写比较方式。

说了这么多还没有说到数据获取成功时候如何通知RecycleView的Adapter进行数据的更新。

还记得ViewModel中的LiveData对象吗???一个实现了观察者模式的对象。

 pagingItemDataViewModel!!.getmLiveData().observe(this, object : Observer> {
            override fun onChanged(t: PagedList?) {
            // 数据更新,通知adapter更新数据
                adapter!!.submitList(t)
            }

        })

一个简单的observe将数据传递给注册了监听的对象。
这与我们以往使用的不一样, adapter!!.submitList(t) 调用的submit方法就是PagedListAdapter中的方法。它来对数据进行更新显示。


结合自己的业务逻辑按照上述的配置即可完成Paing分页库的使用。

Jetpack插件化学习之AndroidX Paging 大数据列表加载库二--使用_第1张图片

有问题,联系我。

[email protected]

image

你可能感兴趣的:(Android)