IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 在Compose中使用Paging分页库 -> 正文阅读

[移动开发]在Compose中使用Paging分页库

前言

大约在两年前,写了一篇Jetpack 系列之Paging3,看这一篇就够了~,本篇文章主要来看,在Compose中如何使用Paging3,这里不得不说一句,在xml中使用Paging3和在Compose中使用仅有UI层代码不同,所以之前定义的接口层、仓库层直接复用直接的代码即可。

Paging3的使用

项目搭建

首先,我们新建项目,在build.gradle中引入compose的paging库,这里将网络请求等依赖库一并引入。代码如下所示:

implementation("androidx.paging:paging-compose:1.0.0-alpha14")
implementation?"com.squareup.retrofit2:retrofit:2.9.0"
implementation?"com.squareup.retrofit2:converter-gson:2.9.0"
implementation?"com.squareup.okhttp3:logging-interceptor:4.9.2"
implementation?"androidx.lifecycle:lifecycle-viewmodel-compose:2.4.1"

API接口准备

API接口我们使用 「鸿洋」大佬?「玩Android」中的查询每日一问接口 :https://wanandroid.com/wenda/list/1/json

这里我们已经写好了RetrofitService类用于创建网络请求的service代码如下所示:

object?RetrofitService?{


????/**
?????*?okhttp?client
?????*/
????lateinit?var?okHttpClient:?OkHttpClient

????/**
?????*?主Url地址
?????*/
????private?const?val?BASEAPI?=?"https://www.wanandroid.com/";


????/**
?????*?创建service对象
?????*/
????fun?<T>?createService(mClass:?Class<T>):?T?{
????????val?builder:?OkHttpClient.Builder?=?OkHttpClient.Builder();
????????okHttpClient?=?builder.build()
????????val?retrofit:?Retrofit?=?Retrofit.Builder()
????????????.baseUrl(BASEAPI)
????????????.client(okHttpClient)
????????????.addConverterFactory(GsonConverterFactory.create())
????????????.build()
????????return?retrofit.create(mClass)?as?T
????}

}

定义DataApi接口,这里我们将方法声明为挂起函数,代码如下所示:

interface?DataApi?{

????/**
?????*?获取数据
?????*/
????@GET("wenda/list/{pageId}/json")
????suspend?fun?getData(@Path("pageId")?pageId:Int):?DemoReqData
}

定义数据源

首先我们来定义数据源DataSource继承自PagingSource,代码如下所示:

class?DataSource():PagingSource<Int,DemoReqData.DataBean.DatasBean>(){
????override?suspend?fun?load(params:?LoadParams<Int>):?LoadResult<Int,?DemoReqData.DataBean.DatasBean>?{
????????TODO("Not?yet?implemented")
????}

????override?fun?getRefreshKey(state:?PagingState<Int,?
?????????????DemoReqData.DataBean.DatasBean>):?Int??{
????????return?null
???}
}

这里具体的含义已经在上篇Paging3文章中讲的很详细了,getRefreshKey方法是新增的,之前没有提到过,这里讲解一下这个方法的用途。

getRefreshKey

getRefreshKey方法意思是 refresh时,从最后请求的页面开始请求,null则请求第一页。

举个例子,请求出错时会调用refresh方法加载 ,如果当前已经请求了第一页到第四页的数据, 可以通过设置在refresh 后会加载第5 - 8页的数据,并且前四页的数据都没了。如果getRefreshKey返回null,refresh后 会重新加载第一到第四页的数据,这里我们直接返回null即可。

DataSource为我们自动生成了load方法,我们主要的请求操作就在load方法中完成。主要代码如下所示:

class?ADataSource?:?PagingSource<Int,?DemoReqData.DataBean.DatasBean>()?{
????override?suspend?fun?load(params:?LoadParams<Int>):?LoadResult<Int,?DemoReqData.DataBean.DatasBean>?{

????????return?try?{

????????????//页码未定义置为1
????????????val?currentPage?=?params.key??:?1
????????????//仓库层请求数据
????????????Log.d("请求页码标记",?"请求第${currentPage}页")
????????????val?demoReqData?=?DataRespority().loadData(currentPage)
????????????//当前页码?小于?总页码?页面加1
????????????val?nextPage?=?if?(currentPage?<?demoReqData.data?.pageCount??:?0)?{
????????????????currentPage?+?1
????????????}?else?{
????????????????//没有更多数据
????????????????null
????????????}

????????????LoadResult.Page(
????????????????data?=?demoReqData.data!!.datas!!,
????????????????prevKey?=?null,
????????????????nextKey?=?nextPage
????????????)

????????}?catch?(e:?Exception)?{
????????????if?(e?is?IOException)?{
????????????????Log.d("测试错误数据",?"-------连接失败")
????????????}
????????????Log.d("测试错误数据",?"-------${e.message}")
????????????LoadResult.Error(throwable?=?e)
????????}

????}

????override?fun?getRefreshKey(state:?PagingState<Int,?DemoReqData.DataBean.DatasBean>):?Int??{
????????return?null
????}

}

接下来我们看下DataRespority仓库层的代码,代码比较简单,如下所示:

class?DataRespority?{

????private?var?netWork?=?RetrofitService.createService(
????????DataApi::class.java
????)

????/**
?????*?查询护理数据
?????*/
????suspend?fun?loadData(
????????pageId:?Int
????):?DemoReqData??{
????????return?try?{
????????????netWork.getData(pageId)
????????}?catch?(e:?Exception)?{
????????????//在这里处理或捕获异常
????????????null
????????}

????}
}

创建viewmodel

创建viewModel对象,并创建pager对象从而调用PagingSource方法 ,代码如下所示:

class?MainActivityViewModel?:?ViewModel()?{

????/**
?????*?获取数据
?????*/
????fun?getData()?=?Pager(PagingConfig(pageSize?=?1))?{
????????DataSource()
????}.flow
}

到这里为止,上面的代码都和我们上篇文章中的代码是一致的,接下来我们主要看UI层的代码如何实现。

实现UI层代码

View层数据请求并将结果显示在View上

val?mainViewmodel:?MainActivityViewModel?=?viewModel()
val?data?=?mainViewmodel.getData().collectAsLazyPagingItems()

首先我们获取viewmodel的示例,这里可以调用viewModel函数需要引入lifecycle-viewmodel-compose库,代码如下所示:

implementation?"androidx.lifecycle:lifecycle-viewmodel-compose:2.4.1"

通过调用collectAsLazyPagingItems方法将结果转为LazyPagingItems实例,在LazyColumn直接调用即可,代码如下所示:

?Column?{
????????LazyColumn()?{
????????????items(items?=?data)?{?item?->
????????????????Message(data?=?item)
????????????}
????????}
????}

Message是数据展示页面对应的compose函数,代码如下所示:

@Composable
fun?Message(data:?DemoReqData.DataBean.DatasBean?)?{
????Card(
????????modifier?=?Modifier
????????????.background(Color.White)
????????????.padding(10.dp)
????????????.fillMaxSize(),?elevation?=?10.dp
????)?{
????????Column(modifier?=?Modifier.padding(10.dp))?{
????????????Text(
????????????????text?=?"作者:${data?.author}"
????????????)
????????????Text(text?=?"${data?.title}")
????????}
????}
}

运行程序,结果下图所示。?

监听Paging3状态

这里我们以refresh时加载为例,代码如下所示:

if?(data.loadState.refresh?is?LoadState.Loading)?{
????Log.d(TAG,?"正在加载")
}?else?if?(data.loadState.refresh?is?LoadState.Error)?{
????when?((data.loadState.refresh?as?LoadState.Error).error)?{
????????is?IOException?->?{
????????????Log.d(TAG,?"网络未连接,可在这里放置失败视图")
????????}
????????else?->?{
????????????Log.d(TAG,?"网络未连接,其他异常")
????????}
????}
}

断开网络,运行程序,打印如下图所示:

这里放置失败视图我们就不再演示了,如果想在失败时刷新的话,直接调用?data.refresh即可。

完整代码如下所示:

@Composable
fun?Greeting()?{
????val?mainViewmodel:?MainActivityViewModel?=?viewModel()
????val?data?=?mainViewmodel.getData().collectAsLazyPagingItems()
????Column?{
????????LazyColumn()?{
????????????items(items?=?data)?{?item?->
????????????????Message(data?=?item)
????????????}

????????????val?TAG?=?"加载状态"

????????????if?(data.loadState.refresh?is?LoadState.Loading)?{
????????????????Log.d(TAG,?"正在加载")
????????????}?else?if?(data.loadState.refresh?is?LoadState.Error)?{
????????????????when?((data.loadState.refresh?as?LoadState.Error).error)?{
????????????????????is?IOException?->?{
????????????????????????Log.d(TAG,?"网络未连接,可在这里放置失败视图")
????????????????????}
????????????????????else?->?{
????????????????????????Log.d(TAG,?"网络未连接,其他异常")
????????????????????}
????????????????}
????????????}
????????}
????}


}

@Composable
fun?Message(data:?DemoReqData.DataBean.DatasBean?)?{
????Card(
????????modifier?=?Modifier
????????????.background(Color.White)
????????????.padding(10.dp)
????????????.fillMaxSize(),?elevation?=?10.dp
????)?{
????????Column(modifier?=?Modifier.padding(10.dp))?{
????????????Text(
????????????????text?=?"作者:${data?.author}"
????????????)
????????????Text(text?=?"${data?.title}")
????????}
????}

}

?这样我们就实现了,在Compose中使用分页库的功能了。

源码地址已上传

源码地址:GitHub - huanglinqing123/ComposePagingDemo: Compose中使用Paging3分页库示例

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-05-13 11:51:34  更:2022-05-13 11:51:59 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 1:22:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码