当前位置: 首页 > news >正文

JetPack系列教程(六):Paging——让分页加载不再“秃”然

前言

在Android开发的世界里,分页加载就像是一场永无止境的马拉松,每次滚动到底部,都仿佛在提醒你:“嘿,朋友,还有更多数据等着你呢!”但别担心,Google大佬们早就看透了我们的烦恼,于是推出了Jetpack Paging组件,让分页加载变得轻松又优雅。今天,我们就来聊聊这个神奇的组件,看看它是如何让我们的开发生活变得更加美好的。[2][8]

Paging是什么?能吃吗?

首先,Paging是一个分页库,它可以帮助我们优雅地渐进加载大型数据集合,同时减少网络带宽和系统资源的消耗。简单来说,就是让你的应用在加载大量数据时,依然能够保持流畅,就像吃了德芙巧克力一样丝滑。[10]

Paging的四大金刚

Paging之所以强大,离不开它的四大核心类:

  1. RecyclerView:负责列表展示,就像餐厅的菜单,把各种美食(数据)展示给顾客(用户)。[2][8]
  2. PagedListAdapter:RecyclerView的适配器,同时负责通知PagedList何时加载更多数据。它就像餐厅的服务员,知道什么时候该上菜(加载数据)。[2][8]
  3. PagedList:控制分页加载的逻辑,比如加载的数量、每页的大小等。它就像餐厅的厨师长,掌控着整个厨房的节奏。[2][8]
  4. DataSource:执行数据获取的逻辑,它本身并不存储数据,获取到数据后丢给PagedList存储。它就像餐厅的采购员,负责把新鲜的食材(数据)带回来。[2][8]

Paging的三大分页术

Paging支持三种分页方式,就像武侠小说里的三大绝学,各有千秋:

  1. PositionalDataSource:支持从任意位置开始,取多少条数据的方式。这就像你在餐厅点菜,说“从第10道菜开始,给我上20道”。[2][8]
  2. PageKeyedDataSource:以页信息加载数据的场景,比如“pageIndex=1&pageSize=20”。这就像你在餐厅说“给我来第一页菜单,每页20道菜”。[2][8]
  3. ItemKeyedDataSource:根据上一条数据的信息加载下一条数据,比如社交评论中的“maxId=nextId&count=200”。这就像你在餐厅说“给我上完这道菜后,再根据这道菜的风格,给我推荐下一道”。[2][8]

实战:用Paging加载GitHub仓库

说了这么多,是时候来点实战了。假设我们要展示GitHub上所有Android相关的开源库,以Star数量排序,每页返回5条数据。[12]

1. 引入依赖

首先,我们需要在build.gradle文件中添加Paging的依赖:

def paging_version = "3.0.0"
implementation "androidx.paging:paging-runtime-ktx:$paging_version"

2. 创建数据模型类

data class Repo(val id: Int,val name: String,val description: String,val starCount: String
)

3. 定义网络请求接口

interface ApiService {@GET("search/repositories?sort=stars&q=Android")suspend fun searRepos(@Query("page") page: Int, @Query("per_page") perPage: Int): RepoResponsecompanion object {private const val BASE_URL = "https://api.github.com/"fun create(): ApiService {return Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(GsonConverterFactory.create()).build().create(ApiService::class.java)}}
}

4. 配置数据源

自定义一个子类继承PagingSource,重写load()函数:

class RepoPagingSource(private val apiService: ApiService) : PagingSource<Int, Repo>() {override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Repo> {return try {val page = params.key ?: 1val pageSize = params.loadSizeval repoResponse = apiService.searRepos(page, pageSize)val repoItems = repoResponse.itemsval prevKey = if (page > 1) page - 1 else nullval nextKey = if (repoItems.isNotEmpty()) page + 1 else nullLoadResult.Page(repoItems, prevKey, nextKey)} catch (e: Exception) {LoadResult.Error(e)}}
}

5. 在ViewModel中实现接口请求

class RepoViewModel : ViewModel() {private val apiService = ApiService.create()fun getPagingData(): Flow<PagingData<Repo>> {return Pager(PagingConfig(pageSize = 5, prefetchDistance = 5)) {RepoPagingSource(apiService)}.flow.cachedIn(viewModelScope)}
}

6. UI层展示数据

在Activity或Fragment中,给RecyclerView设置Adapter,并监听数据变化:

class MainActivity : AppCompatActivity() {private val viewModel by lazy { ViewModelProvider(this).get(RepoViewModel::class.java) }private val adapter: RepoAdapter by lazy { RepoAdapter() }override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val recyclerView: RecyclerView = findViewById(R.id.recyclerView)recyclerView.layoutManager = LinearLayoutManager(this)recyclerView.adapter = adapterlifecycleScope.launchWhenCreated {viewModel.getPagingData().collectLatest { pagingData ->adapter.submitData(pagingData)}}}
}

结语

通过上面的实战,我们可以看到,Paging组件让分页加载变得如此简单。它不仅减少了我们的代码量,还提高了应用的性能和用户体验。[10]所以,下次当你再遇到分页加载的需求时,不妨试试Paging组件,让你的开发生活变得更加轻松愉快![10]

好了,今天的教程就到这里。如果你觉得有用,别忘了点赞、分享和关注哦!我们下期再见!

http://www.dtcms.com/a/330293.html

相关文章:

  • 理财学习资料推荐
  • 谈一些iOS组件化相关的东西
  • C# 多线程:并发编程的原理与实践
  • C++中的STL标准模板库和string
  • Heterophily-aware Representation Learning on Heterogeneous Graphs
  • AI - 工具调用
  • AI智能体记忆策略
  • 10 ABP 模块系统
  • [转]SURREAL数据集国内下载链接
  • Deep Agents:用于复杂任务自动化的 AI 代理框架
  • nm命令和nm -D命令参数
  • 19. 重载的方法能否根据返回值类型进行区分
  • Java之String类
  • 3.Cursor提效应用场景实战
  • UEdior富文本编辑器接入AI
  • 算法篇----分治(归并排序)
  • 云电竞盒子对游戏性能有影响吗?
  • 手游业务怎么做防护
  • 智慧城市数字孪生:城市管理的“平行宇宙”
  • 补环境基础(四) Hook插件
  • 黎阳之光立体物业透明管理:开启智慧物业新时代
  • 设计原则之【抽象层次一致性(SLAP)】,方法也分三六九等
  • 安装Win10怎样跳过欢迎界面
  • ant-design a-from-model的校验
  • poetry
  • 《深入解析C++中的Map容器:键值对存储的终极指南》
  • 基于51单片机zigbee的病房呼叫系统
  • Datawhale AI夏令营 「2025全球AI攻防挑战赛-赛道一:图片全要素交互认证-生成赛」的赛事项目实践
  • springboot接口请求参数校验
  • 双椒派E2000D系统盘制作全攻略