效果视频
简述
本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, 字段用于提示后续引用,此内容需要在协程中使用 - interface GithubService {
- @GET("search/repositories?sort=stars&q=Android")
- suspend fun queryGithubAsync(@Query("per_page")number:Int, @Query("page") page:Int):DetailsBean
- }
复制代码 网络实例
提供三个实例,最终外部需要引用的的为 的实例,具体 依赖注入此处不予说明,有意者可参考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提供的实例中, 中实现了访问网络接口的任务 - 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
我们主要实现 方法;其中 为当前内容页数, 为每页需要加载的内容数量(可在外部进行定义), 为获取的网络数据实体, 为前一页,此处做了一个判断,如果为第一页时,则返回null,否则进行滑动至上一页; 为下一页, 为分页加载所需的内容; 可捕获异常 - 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构造的实例;其中 方法为获取分页的数据,返回为 - Flow<PagingData<DetailBean>>
复制代码类型,其中 外部为固定写法,内部可根据需要自行定义,然后 的配置中,我们需要配置 和 ,如果不定义后者,则通过每页内容数量会是 的三倍,然后添加我们上述创建的 ;最后转化为流,然后置于协程中,它缓存PagingData,以便此流的任何下游集合都将共享相同的数据 - @HiltViewModelclass 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()
复制代码同时如果需要添加底部刷新状态栏、数据错误等标识,需要监听 ,其状态总共分为五种:
- refresh:第一次加载数据触发
- prepend:滑动上一页触发
- append:滑动下一页触发
- source:对应于[PagingSource]中的加载
- mediator:对应于来自[RemoteMediator]的加载
我们此处主要使用 和 ;
其中,在 中进行监听,如果然后数据为null,则显示全屏错误提示,此处为第一次加载数据;
然后,在 中监听 和 两种状态,在其 是显示底部加载状态,在 中显示底部错误提示,此处不同于 的 状态,因为有了数据,就不在需要显示全屏错误提示,在数据列表底部显示错误状态栏即可 - @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()} }
- }
- }
- }
- }
- }
复制代码到此这篇关于Android Hilt Retrofit Paging3使用实例的文章就介绍到这了,更多相关Android Hilt Retrofit Paging3内容请搜索晓枫资讯以前的文章或继续浏览下面的相关文章希望大家以后多多支持晓枫资讯!
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |