网站公司企业网站,政务服务大厅网站建设方案,定制麻将app软件多少钱,统一企业官网一、Paging3介绍
Paging3是jetpack推出的一个分页加载库#xff0c;用于方便开发者实现分页加载功能#xff0c;支持显示加载状态#xff0c;重试机制#xff0c;支持协程与RxJava结合使用#xff0c;相对于传统的分页加载方案#xff0c;我们不需要关注recyclerview的滑…一、Paging3介绍
Paging3是jetpack推出的一个分页加载库用于方便开发者实现分页加载功能支持显示加载状态重试机制支持协程与RxJava结合使用相对于传统的分页加载方案我们不需要关注recyclerview的滑动状态然后根据状态去实时请求接口所有相关的判断逻辑Paging3已经在内部为我们做好了实现我们只需要实现Paging3的提供的抽象方法即可实现分页加载功能
二、Paging3的依赖添加
// Paging3默认使用协程如果不需要使用RxJava则只引入这一个依赖即可
implementation androidx.paging:paging-runtime:3.1.1// 如果需要使用RxJava则需要在引入这个依赖
implementation androidx.paging:paging-rxjava2:3.1.1
三、Paging3的使用
Paging3的使用需要关注三个类
1、PagingDataAdapter
使用方法与RecyclerView的adapter几乎一致需要注意的是PagingDataAdapter默认添加了DiffUtil需要我们手动实现DiffUtil的对比方法
2、Pager
Paging3提供的封装工具提供配置分页参数数据请求形式页面加载逻辑等配置操作
3、SourceFactory
我们需要实现此类用于实现数据的请求与加载逻辑
/*** 时间2022/5/29 00:33 * 作者菜籽* 备注Paging3的数据适配器需要实现DiffUtil方法*/class AdapterPaging3 : PagingDataAdapterItemPaging3, AdapterPaging3.ViewHolder(itemComparator) {companion object {val itemComparator object : DiffUtil.ItemCallbackItemPaging3() {/*** 用来判断新旧条目是否一样确定是否需要刷新* 只有当此方法返回true时才会执行下面的方法* 如果此方法返回false则下面的方法不会执行* 举个例子当前item的布局没有发生变化只是布局里面的数据发生了变化* 比如字符串从AAA变成了BBB则这里返回true表示不需要重绘当前item的布局**/override fun areItemsTheSame(oldItem: ItemPaging3, newItem: ItemPaging3): Boolean {return true}/*** 用来确定是否是同一条目是否一样* 注意与上面的方法区分* 这里返回true时只会刷新当前item布局中发生变化的那一部分UI其余地方不需要动* 如果这里返回false则当前item不会刷新显示内容也不会发生变化*/override fun areContentsTheSame(oldItem: ItemPaging3, newItem: ItemPaging3): Boolean {return !TextUtils.equals(oldItem.title, newItem.title)}}}class ViewHolder(view: View) : RecyclerView.ViewHolder(view)override fun onBindViewHolder(holder: ViewHolder, position: Int) {holder.itemView.tv_title.text getItem(position)?.title}override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {val view LayoutInflater.from(parent.context).inflate(R.layout.layout_item_paging3, parent, false)return ViewHolder(view)}}
val pagingConfig PagingConfig(/*** 每页显示的数据数量* 注意这个页并不等同于我们接口中定义的条数* 这个数量的意思是每一个页面会加载这么多数据* 举个例子如果接口每页返回10条而这里定义了20条则Paging3会请求两次接口* 用来拼成这20条数据*/pageSize 60,// 开启占位符在加载到正确数据之前显示的item布局enablePlaceholders true,// 预刷新的距离距离最后一个 item 多远时加载数据prefetchDistance 3,/*** 初始化加载数量默认为 pageSize * 3** internal const val DEFAULT_INITIAL_PAGE_MULTIPLIER 3* val initialLoadSize: Int pageSize * DEFAULT_INITIAL_PAGE_MULTIPLIER*/initialLoadSize 60,/*** 一次应在内存中保存的最大数据* 超出这个数字的数据会被销毁当页面滑回来时会重新请求此页面的数据* 滑动加载更多的数据*/maxSize 200
)
/*** 时间2022/5/29 00:35* 作者菜籽* 备注使用viewModel协程的形式来请求数据*/class Paging3Coroutines {private val repository by lazy {val config PagingConfig(pageSize 20, initialLoadSize 5, maxSize 150)val sourceFactory object : PagingSourceInt, ItemPaging3() {/*** 官方解释每当paging想要加载新的数据来代替当前列表时会发生刷新操作回调到这个方法** 使用场景* 比如说你当前是第三页然后用户此时回到第二页时数据发生变化了不再前面加载好的数据了* 此时就可以在这里返回第二页的索引它会重新请求第二页的内容用来展示** 目前还没有遇到过这种需求*/override fun getRefreshKey(state: PagingStateInt, ItemPaging3): Int? {return null}/*** 我这里定义的为每页显示10条数据* 模拟网络加载失败的情况*/override suspend fun load(params: LoadParamsInt): LoadResultInt, ItemPaging3 {val currentPage params.key ?: 0Log.d(ItemDataSource, currentPage:$currentPage)if (currentPage 0) {val random Math.random()delay((random * 3000).toLong())}val list mutableListOfItemPaging3()for (i in 0..9) {list.add(ItemPaging3(第 (10 * currentPage i) 条))}val prevKey if (currentPage 0) null else currentPage - 1val nextKey currentPage 1if (!NetStateHelper.isConnect) {return LoadResult.Error(ConnectException())}if (currentPage 4) {// nextKey为null表示数据加载到头了return LoadResult.Page(list, prevKey, null)}return LoadResult.Page(list, prevKey, nextKey)}}Pager(config, pagingSourceFactory { sourceFactory })}fun getData() repository.flow.asLiveData()}
四、高级用法
1、显示加载状态
Paging3支持设置header和footer用来显示当前的加载状态我们需要声明一个adapter实现LoadStateAdapter来显示加载状态具体代码如下
/*** 时间2022/5/28 23:32* 作者菜籽* 备注网络状态的适配器*/class LoadStateAdapterPaging3 : LoadStateAdapterLoadStateAdapterPaging3.LoadStateViewHolder() {class LoadStateViewHolder(view: View) : RecyclerView.ViewHolder(view)private var listener: (() - Unit)? nullfun setOnReloadClickListener(listener: () - Unit) {this.listener listener}/*** loadState 有三种状态**/override fun onBindViewHolder(holder: LoadStateViewHolder, loadState: LoadState) {Log.d(ItemDataSource, loadState:$loadState)holder.itemView.progress_bar.visibility View.VISIBLEholder.itemView.tv_state.text 正在加载中...if (loadState is LoadState.NotLoading) {if (loadState.endOfPaginationReached) {holder.itemView.progress_bar.visibility View.GONEholder.itemView.tv_state.text 数据加载完毕} else {holder.itemView.tv_state.text 滑到头了继续加载}return}if (loadState is LoadState.Error) {holder.itemView.tv_state.text 加载失败点击重试holder.itemView.progress_bar.visibility View.GONEholder.itemView.setOnClickListener {listener?.invoke()}return}}override fun onCreateViewHolder(parent: ViewGroup, loadState: LoadState): LoadStateViewHolder {val view LayoutInflater.from(parent.context).inflate(R.layout.load_state_item_paging3, parent, false)return LoadStateViewHolder(view)}/*** 是否显示当前的加载状态* 默认的是只有 loading中loading失败时才会显示加载状态* 我们可以改掉super的代码添加一条当加载完成时也显示加载状态*/override fun displayLoadStateAsItem(loadState: LoadState): Boolean {//return super.displayLoadStateAsItem(loadState)return loadState is LoadState.Loading || loadState is LoadState.Error || (loadState is LoadState.NotLoading loadState.endOfPaginationReached)}}
2、与数据展示相结合
//通过融合两个adapter实现数据适配器与页面加载适配器融合
adapter.withLoadStateFooter(loadAdapter)3、与RxJava相结合
/*** 时间2022/5/29 00:39 * 作者菜籽* 备注Paging3与RxJava结合使用*/class Paging3RxJava {private val repository by lazy {val config PagingConfig(pageSize 20, initialLoadSize 5, maxSize 150)val sourceFactory object : RxPagingSourceInt, ItemPaging3() {override fun getRefreshKey(state: PagingStateInt, ItemPaging3): Int? {return null}override fun loadSingle(params: LoadParamsInt): SingleLoadResultInt, ItemPaging3 {val currentPage params.key ?: 0val delay if (currentPage 0) {val random Math.random()random * 3000} else {0f}.toLong()return Single.just().delay(delay, TimeUnit.MILLISECONDS).map {val list mutableListOfItemPaging3()for (i in 0..9) {list.add(ItemPaging3(第 (10 * currentPage i) 条))}val prevKey if (currentPage 0) null else currentPage - 1val nextKey currentPage 1if (!NetStateHelper.isConnect) {returnmap LoadResult.Error(ConnectException())}if (currentPage 4) {// nextKey为null表示数据加载到头了returnmap LoadResult.Page(list, prevKey, null)}returnmap LoadResult.Page(list, prevKey, nextKey)}}}Pager(config, pagingSourceFactory { sourceFactory })}fun getData() repository.flow.asLiveData()}