Android Hilt Retrofit Paging3使用实例
作者:FranzLiszt1847 发布时间:2022-11-20 21:06:59
效果视频
简述
本Demo采用Hilt+Retrofit+Paging3完成,主要为了演示paging3分页功能的使用,下列为Demo所需要的相关依赖
//retrofit
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
//paging
implementation 'androidx.paging:paging-runtime:3.1.1'
implementation 'androidx.paging:paging-compose:1.0.0-alpha14'
//Dagger - Hilt
implementation("com.google.dagger:hilt-android:2.44")
kapt("com.google.dagger:hilt-android-compiler:2.44")
// Compose dependencies
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1"
implementation "androidx.hilt:hilt-navigation-compose:1.0.0"
// Coroutines
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.1'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
Hilt+Retrofit
访问接口
定义需要访问的接口,此接口是Github api,suspend
字段用于提示后续引用,此内容需要在协程中使用
interface GithubService {
@GET("search/repositories?sort=stars&q=Android")
suspend fun queryGithubAsync(@Query("per_page")number:Int, @Query("page") page:Int):DetailsBean
}
网络实例
提供三个实例,最终外部需要引用的的为UseCase
的实例,具体Hilt
依赖注入此处不予说明,有意者可参考Hilt依赖注入
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
const val BASE_URL:String = "https://api.github.com/"
@Singleton
@Provides
fun providerRetrofit():Retrofit{
return Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
}
@Singleton
@Provides
fun providerGithubService(retrofit: Retrofit): GithubService {
return retrofit.create(GithubService::class.java)
}
@Singleton
@Provides
fun providerUseCase(service: GithubService):UseCase{
return UseCase(GetProjects(service))
}
}
在Hilt提供的实例中,UseCase
中实现了访问网络接口的任务
data class UseCase(
val getProjects: GetProjects
)
class GetProjects(private val service: GithubService) {
suspend operator fun invoke(number:Int,page:Int): DetailsBean {
return service.queryGithubAsync(number, page)
}
}
PagingSource
我们主要实现load
方法;其中page
为当前内容页数,pageSize
为每页需要加载的内容数量(可在外部进行定义),repository
为获取的网络数据实体,previousPage
为前一页,此处做了一个判断,如果为第一页时,则返回null,否则进行滑动至上一页;nextPage
为下一页, LoadResult.Page
为分页加载所需的内容; LoadResult.Error
可捕获异常
class DataPagingSource(private val useCase: UseCase):PagingSource<Int,DetailBean>() {
override fun getRefreshKey(state: PagingState<Int, DetailBean>): Int? = null
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, DetailBean> {
return try {
val page = params.key ?: 1 //当前页,默认第一页
val pageSize = params.loadSize //每页数据条数
val repository = useCase.getProjects(page,pageSize) //获取的数据源
val repositoryItem = repository.beans //获取的数据列表
val previousPage = if (page > 1) page - 1 else null //前一页
val nextPage = if (repositoryItem.isNotEmpty()) page+1 else null //下一页
Log.d("hiltViewModel","page=$page size=$pageSize")
LoadResult.Page(repositoryItem,previousPage,nextPage)
}catch (e:Exception){
LoadResult.Error(e)
}
}
}
ViewModel
在构造函数中调用Hilt构造的实例;其中getData
方法为获取分页的数据,返回为Flow<PagingData<DetailBean>>
类型,其中Flow<PagingData<...>>
外部为固定写法,内部可根据需要自行定义,然后PagingConfig
的配置中,我们需要配置pageSize
和initialLoadSize
,如果不定义后者,则通过每页内容数量会是pageSize
的三倍,然后添加我们上述创建的PagingSource
;最后转化为流,然后置于协程中,它缓存PagingData,以便此流的任何下游集合都将共享相同的数据
@HiltViewModel
class HomeViewModel @Inject constructor(private val useCase: UseCase):ViewModel() {
val PAGE_SIZE = 10
fun getData():Flow<PagingData<DetailBean>>{
return Pager(
config = PagingConfig(pageSize = PAGE_SIZE, initialLoadSize = PAGE_SIZE),
pagingSourceFactory = { DataPagingSource(useCase) }
).flow.cachedIn(viewModelScope)
}
}
View
获取ViewModel中的数据
val datas = viewModel.getData().collectAsLazyPagingItems()
同时如果需要添加底部刷新状态栏、数据错误等标识,需要监听loadState
,其状态总共分为五种:
refresh:第一次加载数据触发
prepend:滑动上一页触发
append:滑动下一页触发
source:对应于[PagingSource]中的加载
mediator:对应于来自[RemoteMediator]的加载
我们此处主要使用refresh
和append
;
其中,在refresh
中进行监听,如果然后数据为null,则显示全屏错误提示,此处为第一次加载数据;
然后,在append
中监听loading
和Error
两种状态,在其loading
是显示底部加载状态,在Error
中显示底部错误提示,此处不同于refresh
的Error
状态,因为有了数据,就不在需要显示全屏错误提示,在数据列表底部显示错误状态栏即可
@Composable
fun GithubList(viewModel: HomeViewModel = hiltViewModel()){
val datas = viewModel.getData().collectAsLazyPagingItems()
LazyColumn(
verticalArrangement = Arrangement.spacedBy(10.dp),
modifier = Modifier
.background(grey)
.fillMaxSize()
.padding(10.dp)
){
when(datas.loadState.refresh){
is LoadState.Loading-> {item { loading() }}
is LoadState.Error-> {
if (datas.itemCount <= 0){
item{
/**
* 全屏显示错误*/
failedScreen() {
datas.retry()
}
}
}
}
}
itemsIndexed(datas){ _, value ->
if (value != null){
GithubItem(value)
}else{
empty {
datas.retry()
}
}
}
when(datas.loadState.append){
is LoadState.NotLoading-> {}
is LoadState.Loading-> {
item {
loading()
}
}
is LoadState.Error-> {
if (datas.itemCount > 0){
/**
* 底部显示加载错误*/
item { failed(){datas.retry()} }
}
}
}
}
}
来源:https://blog.csdn.net/News53231323/article/details/128678134
猜你喜欢
- Guava Cache:⾕歌开源缓存框架Guava Cache是在内存中缓存数据,相比较于数据库或redis存储,访问内存中的数据会更加高效
- 第 1 步:将这个 Spring Boot 项目的打包方式设置为 war。<packaging>war</packagin
- 本文实例为大家分享了Android自定义输入法软键盘的具体代码,供大家参考,具体内容如下1 功能描述触屏设备主界面中有一个文本编辑框,底部区
- 目录一、集合框架的概述二、集合框架(Java集合可分为Collection 和 Map 两种体系)三、Collection接口中的方法的使用
- 比如,现在有一些图形,需要计算他们的面积,计算面积的方法都不一样,可以这么做声明一个抽象类//基类 abstrac
- 什么是https要说https我们得先说SSL(Secure Sockets Layer,安全套接层),这是一种为网络通信提供安全及数据完整
- 一、MessageBox弹出框MessageBox.Show(<字符串> Text, <字符串> Title, &l
- Java音频播放,因为必须依赖到本地环境,所以JAVA在音频处理方面优势不大,或者说打从Java体系开发时就没太多的考虑音频播放
- 线程池类图我们最常使用的Executors实现创建线程池使用线程主要是用上述类图中提供的类。在上边的类图中,包含了一个Executor框架,
- PrintStream 介绍PrintStream 是打印输出流,它继承于FilterOutputStream。PrintStream 是用
- 用户提出一个需求:当修改产品价格的时候,需要记录操作日志,什么时候做了什么事情。想必这个案例,只要是做过应用系统的小伙伴们,都应该遇到过吧?
- 本文实例为大家分享了C#仿Windows XP自带的扫雷游戏的具体代码,供大家参考,具体内容如下1 题目描述:模仿Windows XP自带的
- SpringCloud是分布式微服务架构的一站式解决方案,十多种微服务架构落地技术的集合体,俗称微服务全家桶SpringCloud和Spri
- 1、Java数组介绍在Java中,数组是用来存放同一种数据类型的集合,注意只能存放同一种数据类型(Object类型数组除外)。①、数组的声明
- 目录1、Integer a = 1;2、对于同一类中的两个方法 , 在判断它们是不是重载方法时 , 肯定不考虑( )3、对于Java中异常的
- 1.java创建自定义类数组方法:Student []stu = new Student[3];for(int i = 0; i <
- 目录前言正文自定义NameSpaceHandler自定义schemaParserDecorator总结前言在早期基于Xml配置的Spring
- 前言设计模式在我看来更像是一种设计思维或设计思想,它就像《孙子兵法》一样,为你的项目工程提供方向,让你的项目工程更加健壮、灵活,延续生命力。
- 本文实例讲述了C#使用IComparer自定义List类实现排序的方法。分享给大家供大家参考。具体如下:List类中不带参数的Sort函数可
- 本文实例讲述了C#4.0新特性的协变与逆变,有助于大家进一步掌握C#4.0程序设计。具体分析如下:一、C#3.0以前的协变与逆变如果你是第一