在Jetpack Compose中使用Paging 3实现无限滚动

在Jetpack Compose中使用Paging 3实现无限滚动

本文将介绍在Jetpack Compose中进行分页加载。分页加载意味着一次只加载应用程序中的小数据块。
假设您在服务器上有大量数据,并且您希望在UI上显示这些数据。显然,您不希望一次性加载所有数据。您希望每次只加载少量数据。
这就是分页的作用,当您在应用程序中向上滚动时,它会加载下一组数据,通过这种方式可以提高应用程序的性能。

基本上,我们将构建一个非常简单的应用程序,通过使用paging 3库在RecyclerView上显示狗的图像。最好的部分是您可以进行无限滚动,而不必担心应用程序的性能问题。

如上所示,在上面的视频中,我们正在RecyclerView上显示狗的图像,最好的部分是当我们向下滚动时,图像是动态加载的。

//Dependencies
val daggerHilt = "2.47"
val coroutine = "1.7.1"//dagger hilt
implementation("com.google.dagger:hilt-android:$daggerHilt")
kapt("com.google.dagger:hilt-android-compiler:$daggerHilt")
implementation("androidx.hilt:hilt-navigation-compose:1.1.0-alpha01")//coroutines
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutine")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutine")
implementation("androidx.lifecycle:lifecycle-runtime-compose:2.7.0-alpha02")//paging 3
implementation ( "androidx.paging:paging-runtime-ktx:3.2.1")
implementation ("androidx.paging:paging-compose:3.3.0-alpha02")//retrofit
implementation ("com.squareup.retrofit2:retrofit:2.9.0")
//moshi
implementation("com.squareup.moshi:moshi-kotlin:1.12.0")
implementation ("com.squareup.retrofit2:converter-moshi:2.9.0")//coil
implementation("io.coil-kt:coil-compose:2.4.0")

这些是我们用于构建此应用程序的依赖项。确保您已经了解dagger hilt、coroutines和retrofit,因为我们只会谈论Paging 3。

Model

data class DogsModel(val id:String,val url:String
)

首先,我们创建了一个DogsModel文件,它只是一个模式,以便我们可以将其中的数据绑定在一起。

interface ApiService {companion object {const val BASE_URL = "https://api.thedogapi.com"}@GET("v1/images/search")suspend fun getAllDogs(@Query("page") page: Int,@Query("limit") limit: Int): List<DogsModel>
}

如您所见,在上面的代码中,我们使用https://api.thedogapi.com API获取狗的图像。

请注意查询参数中,我们传递了页面和限制。当您向下滚动时,页码将增加,而限制将是您想要一次加载的图像数量。

Repository

class DogsRepository @Inject constructor(private val apiService:ApiService
) {suspend fun getDogs(page:Int,limit:Int):List<DogsModel> = apiService.getAllDogs(page,limit)
}

之后,我们创建了一个存储库,在其中编写从服务器获取数据的逻辑。

正如您在上面的图像中所注意到的那样,在创建存储库之后,我们必须创建一个PagingSource类,在其中编写我们的分页逻辑。

忘记RemoteMediator,它用于缓存我们在本文中未使用的数据。

class DogsPagingSource @Inject constructor(private val repository:DogsRepository
) :PagingSource<Int,DogsModel>() {override fun getRefreshKey(state:PagingState<Int,DogsModel> ):Int?= state.anchorPositionoverride suspend fun load(params:LoadParams<Int> ) :LoadResult<Int,DogsModel> {val page = params.key?1val response = repository.getDogs(page,params.loadSize )return try {LoadResult.Page(data=response,prevKey=if (page == 1) null else page.minus(1),nextKey=if (response.isEmpty()) null else page.plus(1))} catch (e: IOException) {LoadResult.Error(e)} catch (e: HttpException) {LoadResult.Error(e)}}
}

如您所见,我们创建了一个DogsPagingSource类,该类扩展了PagingSource<Int,DogsModel>()类,这将有助于编写分页逻辑。
<Int,DogsModels>()中的Int表示它将以Int值作为页码输入,DogsModel是服务器响应。
它将覆盖两个重要函数,getRefreshKey函数将帮助您在要刷新数据时使用,它还会获取有关当前加载数据的信息。
load()这里我们将编写实际的分页逻辑。
正如您注意到的,它返回LoadResult,它是包含PageError子数据类的密封类。
在成功时,我们将返回Page,否则为Error。
使用LoadParams,我们将找到页面编号和限制,如果无法找到页面编号,则将其传递为1。
LoadResult.Page中,我们传递响应(从服务器返回的任何结果)。
prevKey中,如果仅有一页可用,则传递null,否则在向上滚动时减少页面编号。
nextKey中,如果响应为空,则表示没有可用页面,否则在向下滚动时增加页面编号。
在向上滚动的情况下,我们将减少页面编号,在向下滚动的情况下,我们将增加页面编号。

ViewModel


@HiltViewModel
class DogsViewModel @Inject constructor(private val dogsPagingSource: DogsPagingSource
) : ViewModel() {private val _dogResponse: MutableStateFlow<PagingData<DogsModel>> =MutableStateFlow(PagingData.empty())var dogResponse = _dogResponse.asStateFlow()private setinit {viewModelScope.launch {Pager(config = PagingConfig(10, enablePlaceholders = true)) {dogsPagingSource}.flow.cachedIn(viewModelScope).collect {_dogResponse.value = it}}}
}

在上面的代码中,我们创建了一个ViewModel,_dogResponse变量的类型是PagingData<T>,它存储来自DogsPagingSource的结果。

init{}块中,我们调用了Pager,它将limitPagingSource作为必要参数,并返回结果。

让我们在UI上收集这个结果。

@Composable
fun DogsScreen(modifier: Modifier = Modifier,viewModel: DogsViewModel = hiltViewModel()
) {val response = viewModel.dogResponse.collectAsLazyPagingItems()LazyVerticalStaggeredGrid(columns = StaggeredGridCells.Fixed(3),modifier = modifier.fillMaxSize()) {items(response.itemCount) {AsyncImage(model = ImageRequest.Builder(LocalContext.current).data(response[it]?.url ?: "-").crossfade(true).build(),placeholder = painterResource(R.drawable.ic_launcher_foreground),contentDescription = "",contentScale = ContentScale.Crop,modifier = Modifier.padding(20.dp).clip(CircleShape))}response.apply {when {loadState.refresh is LoadState.Loading || loadState.append is LoadState.Loading -> {item {Box(modifier = Modifier.fillMaxWidth(),contentAlignment = Alignment.Center) {CircularProgressIndicator(modifier = Modifier.align(Alignment.Center))}}}loadState.refresh is LoadState.Error || loadState.append is LoadState.Error -> {item {Text(text = "Error")}}loadState.refresh is LoadState.NotLoading -> {}}}}}

如您所见,首先我们创建了ViewModel的对象,通过collectAsLazyPagingItems()来收集响应。
我们使用LazyVerticalStaggeredGrid来通过Coil库显示图像。
这里的load.refresh表示当您首次加载/出错数据时,而load.append表示当您向下滚动时追加加载/出错数据。

Github

https://github.com/nameisjayant/compose-blogs-repository/tree/main/app/src/main/java/com/nameisjayant/articlesrepository/ui/paging3

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/176165.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JavaEE-cookie和session

本部分内容包括 cookie基本概念&#xff0c;sendcookies和getcookies代码&#xff1b; session基本概念&#xff0c;session实现登陆界面&#xff1b; 上述过程中涉及的代码如下&#xff1a; 1 import javax.servlet.ServletException; import javax.servlet.annotation.WebSe…

测开 (Junit 单元测试框架)

目录 了解 Junit 引入相关依赖 1、Junit注解 Test BeforeEach、BeforeAll AfterEach && AfterAll 2、断言 1、Assertions - assertEquals 方法 2、Assertions - assertNotEquals 方法 3、Assertions - assertTrue && assertFalse方法 4、Assertions…

python随手小练14

题目&#xff1a; 文件操作 &#xff1a; 根据文件要求&#xff08;测试&#xff09;筛选出数据并且放入一个新的文件 具体操作&#xff1a; f1 open("1.txt","r",encoding"UTF-8") f2 open("2.txt","w",encoding"U…

JVM 类加载的过程

JVM 类加载的过程 加载验证准备解析初始化 加载 “加载”&#xff08;Loading&#xff09;阶段是整个“类加载”&#xff08;Class Loading&#xff09;过程中的一个阶段&#xff0c;它和类加载 Class Loading 是不同的&#xff0c;一个是加载 Loading 另一个是类加载 Class L…

【Linux进程控制】进程控制专篇

【Linux进程控制】进程控制专篇 目录 【Linux进程控制】进程控制专篇进程创建fork函数写实拷贝fork常规用法fork调用失败的原因 进程终止进程退出场景进程常见退出方法_exit函数return退出 进程等待进程等待必要性进程等待的方法获取子进程status 具体代码实现进程程序替换替换…

Django 社区志愿者管理系统

摘 要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 社区志愿者服务管理系统&#xff0c;主要的模块包括查看首页、个人中心、通知公告管理、志愿者管理、普通管理员管理、志愿活动管理、活动宣…

day02 矩阵 2023.10.26

1.矩阵 2.矩阵乘法 3.特殊矩阵 4.逆矩阵 5.正交矩阵 6.几何意义 7.齐次坐标 8.平移矩阵 9.旋转矩阵 10.缩放矩阵 11.复合运算

浪潮信息inMerge超融合 刷新全球vSAN架构虚拟化VMmark最佳成绩

近日&#xff0c;在国际权威的VMmark测试中&#xff0c;浪潮信息inMerge1100超融合产品搭载NF5280M7服务器&#xff0c;满载运行44Tiles取得40.95分的成绩&#xff0c;刷新了vSAN架构&#xff08;Intel双路最新平台&#xff09;虚拟化性能测试纪录。该测试结果证明inMerge1100可…

hdlbits系列verilog解答(移位寄存器)-23

文章目录 一、问题描述二、verilog源码三、仿真结果 一、问题描述 您将获得一个具有两个输入和一个输出的模块 my_dff &#xff08;实现 D 触发器&#xff09;。实例化其中的三个&#xff0c;然后将它们链接在一起以形成长度为 3 的移位寄存器。端口 clk 需要连接到所有实例。…

linux查看系统版本、内核信息、操作系统类型版本

1. 使用 uname 命令&#xff1a;这将显示完整的内核版本信息&#xff0c;包括内核版本号、主机名、操作系统类型等。 uname -a2. 使用 lsb_release 命令&#xff08;仅适用于支持 LSB&#xff08;Linux Standard Base&#xff09;的发行版&#xff09;&#xff1a;这将显示包含…

如何优雅地单元测试 Kotlin/Java 中的 private 方法?

翻译自 https://medium.com/mindorks/how-to-unit-test-private-methods-in-java-and-kotlin-d3cae49dccd ❓如何单元测试 Kotlin/Java 中的 private 方法❓ 首先&#xff0c;开发者应该测试代码里的 private 私有方法吗&#xff1f; 直接信任这些私有方法&#xff0c;测试到…

Servlet 上下文参数

7)Servlet上下文对象&#xff1a;ServletContext生活中的例子&#xff1a;张三和李四在不远处窃窃私语&#xff0c;并且频繁的对着你坏笑。你肯定会跑过去问&#xff1a;你们俩在聊什么&#xff1f;注意&#xff1a;此处的聊什么&#xff0c;其实就是你在咨询他们聊天的上下文&…

FreeRTOS深入教程(队列内部机制和源码分析)

文章目录 前言一、队列结构体分析二、创建队列三、读写队列源码分析1.读队列源码分析2.写队列源码分析 总结 前言 本篇文章主要来为大家分析队列的内部机制和源码实现。 一、队列结构体分析 在FreeRTOS中队列会使用一个结构体来表示&#xff1a; 1.int8_t * pcHead 和 int…

V90PN总线伺服梯形加减速速度控制(标准报文1应用)

V90 PN总线伺服速度控制应用可以利用标准报文1和SinaSpeed功能块实现,具体代码介绍请查看下面相关文章链接,这里不再赘述。 速度随动控制 V90伺服PN总线速度随动控制(手摇轮功能)-CSDN博客文章浏览阅读40次。V90PN总线控制相关内容,请参考下面文章链接:博途1200/1500PLC …

使用tensorflow创建自己的量化金融工具

介绍 在充满活力的金融领域,高频交易 (HFT) 已经成为游戏规则的改变者。高频交易能够在几毫秒内执行数千个订单,利用先进的算法和计算技术实时利用微小的价格差异。随着金融市场的不断发展,支持高频交易策略的工具和框架也必须不断发展。在这一背景下,TF Quant Finance (T…

物联网AI MicroPython传感器学习 之 SHT3X温湿度传感器

学物联网&#xff0c;来万物简单IoT物联网&#xff01;&#xff01; 一、产品简介 Sensirion SHT3x-DIS湿度和温度传感器基于CMOSens传感器芯片&#xff0c;更加智能、可靠&#xff0c;精度更高。SHT3x-DIS具有增强的信号处理能力、两个独特的用户可选I2C地址&#xff0c;通信…

JavaScript基础知识19——循环结构:while循环

哈喽&#xff0c;你好&#xff0c;我是雷工。 本节学习JavaScript基础语法的循环结构&#xff1a;while循环&#xff0c;以下为学习笔记。 while循环 循环概念&#xff1a;重复执行一些操作&#xff1b; 循环特征&#xff1a;不断地重复&#xff1b; while&#xff1a;在…期间…

监控浏览器页面展示性能的工具

B/S架构&#xff0c;用户都是使用浏览器访问后端服务&#xff0c;产品在开发时需要关注用户的体验&#xff0c;不仅包含交互的友好&#xff0c;性能指标也非常重要。对于后端开发常见的性能指标&#xff0c;可能包含&#xff1a;reponse time&#xff0c;吞吐量等。此外&#x…

【数据结构】顺序表

今天给大家带来的是顺序表相关知识的分享&#xff0c;喜欢的朋友可以三连一波&#xff01;&#xff01;&#xff01; 顺序表 顺序表的基本结构&#xff1a; 顺序表的实现 我们将顺序表的实现分装成函数大概分为下面几类&#xff1a; //初始化 void InitSL(SL* psl); //打印数…

最新waymo数据集 百度网盘

最新waymo数据集介绍 waymo数据集是有史以来最大&#xff0c;最多样化的自动驾驶数据集&#xff0c;包含 传感器数据边界框数据2D视频全景分割标签关键点标签3D语义分割标签2D和3D边界框的关联 是该领域质量最高、规模最大的数据集之一&#xff0c;用于帮助研究界在机器感知…