开发者

Android Hilt Retrofit Paging3使用实例

开发者 https://www.devze.com 2023-01-17 10:20 出处:网络 作者: FranzLiszt1847
目录效果视频简述Hilt+Retrofit访问接口网络实例PagingSourceViewModelView效果视频 简述
目录
  • 效果视频
  • 简述
  • Hilt+Retrofit
    • 访问接口
    • 网络实例
  • PagingSource
    • ViewModel
      • View

        效果视频

        Android Hilt Retrofit Paging3使用实例

        简述

        本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
            im开发者_JAV培训plementation '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.beanjavascripts //获取的数据列表
                   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")
                  BGspDGQHl LoadResult.Page(repositoryItem,previousPage,nextPage)
               }catch (e:Exception){
                   LoadResult.Error(e)
               }
            }
        }
        

        ViewModel

        在构造函数中调用Hilt构造的实例;其中getData方法为获取分页的数据,返回为Flow<PagingData<DetailBean>>类型,其中Flow<PagingData<...>>外部为固定写法,内部可根据需要自行定义,然后PagingConfig的配置中,我们需要配置pageSizeinitialLoadSize,如果不定义后者,则通过每页内容数量会是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]的加载

        我们此处主要使用refreshappend

        其中,在refresh中进行监听,如果然后数据为null,则显示全屏错误提示,此处为第一次加载数据;

        然后,在append中监听loadingError两种状态,在其loading是显示底部加载状态,在Error中显示底部错误提示,此处不同于refreshError状态,因为有了数据,就不在需要显示全屏错误提示,在数据列表底部显示错误状态栏即可

        @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)
            ){
              www.devze.com  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内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

        0

        精彩评论

        暂无评论...
        验证码 换一张
        取 消

        关注公众号