android paging使用教程

以下是基于最新 Paging3 的 Android 分页库使用教程,结合官方文档和开发者实践总结:

一、基础配置

添加依赖

复制代码
// build.gradle  
dependencies {
    def paging_version = "3.2.1"
    implementation "androidx.paging:paging-runtime:$paging_version" 
    implementation "androidx.paging:paging-compose:$paging_version"  // Compose 支持 
    testImplementation "androidx.paging:paging-testing:$paging_version" 
}

核心组件

PagingSource:定义数据加载逻辑

Pager:配置分页参数并生成 PagingData 流

PagingDataAdapter:适配 RecyclerView 或 Compose 列表

RemoteMediator(可选):处理网络+本地缓存的分页协调

二、基础分页实现(纯网络请求)

创建 PagingSource

复制代码
class ArticlePagingSource(private val api: ApiService) : PagingSource<Int, Article>() {
    override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Article> {
        return try {
            val page = params.key  ?: 1
            val response = api.getArticles(page) 
            LoadResult.Page(
                data = response.articles, 
                prevKey = if (page > 1) page - 1 else null,
                nextKey = if (response.hasMore)  page + 1 else null 
            )
        } catch (e: Exception) {
            LoadResult.Error(e)
        }
    }
}

ViewModel 中配置 Pager

复制代码
class ArticleViewModel : ViewModel() {
    private val api = RetrofitClient.apiService  
 
    val articles = Pager(
        config = PagingConfig(
            pageSize = 20,
            enablePlaceholders = false,
            initialLoadSize = 40 
        ),
        pagingSourceFactory = { ArticlePagingSource(api) }
    ).flow.cachedIn(viewModelScope) 
}

UI 层实现(RecyclerView)

// Adapter

复制代码
class ArticleAdapter : PagingDataAdapter<Article, ArticleViewHolder>(DIFF_CALLBACK) {
    companion object {
        val DIFF_CALLBACK = object : DiffUtil.ItemCallback<Article>() {
            override fun areItemsTheSame(oldItem: Article, newItem: Article) = 
                oldItem.id  == newItem.id  
            override fun areContentsTheSame(oldItem: Article, newItem: Article) = 
                oldItem == newItem 
        }
    }
}

// Activity/Fragment

复制代码
lifecycleScope.launch  {
    viewModel.articles.collectLatest  { pagingData ->
        adapter.submitData(pagingData) 
    }
}

三、进阶场景(网络+数据库)

使用 RemoteMediator

复制代码
@ExperimentalPagingApi 
class ArticleRemoteMediator(
    private val db: AppDatabase,
    private val api: ApiService 
) : RemoteMediator<Int, Article>() {
 
    override suspend fun load(
        loadType: LoadType,
        state: PagingState<Int, Article>
    ): MediatorResult {
        // 实现网络请求与数据库缓存的协调逻辑 
        // 详见官方示例:https://github.com/android/architecture-components-samples/tree/main/PagingWithNetworkSample  
    }
}

Room 集成

复制代码
@Dao 
interface ArticleDao {
    @Query("SELECT * FROM articles ORDER BY timestamp DESC")
    fun articlesPagingSource(): PagingSource<Int, Article>
}

// 创建 Pager 时组合 RemoteMediator

复制代码
Pager(
    config = PagingConfig(pageSize = 20),
    remoteMediator = ArticleRemoteMediator(db, api),
    pagingSourceFactory = { db.articleDao().articlesPagingSource()  }
)

四、状态监听与 UI 反馈

// 监听加载状态

复制代码
adapter.addLoadStateListener  { loadState ->
    when (loadState.refresh)  {
        is LoadState.Loading -> showLoading()
        is LoadState.NotLoading -> hideLoading()
        is LoadState.Error -> showError()
    }
}

// 错误重试

复制代码
binding.retryButton.setOnClickListener  {
    adapter.retry() 
}

五、最佳实践建议

性能优化

使用 cachedIn() 缓存数据流

合理设置 PagingConfig 参数(prefetchDistance 等)

实现高效的 DiffUtil 对比逻辑

测试策略

使用 TestPager 和 TestDispatcher 进行单元测试

验证边界条件(空列表、单页数据、加载错误等)

架构整合

配合 ViewModel + LiveData/Flow 使用

通过 Hilt/Dagger 实现依赖注入

结合 SwipeRefreshLayout 实现下拉刷新

完整实现示例可参考 Google 官方示例仓库 ,或通过 查看实际项目集成方式。

相关推荐
alexhilton1 小时前
为什么你的App总是忘记所有事情
android·kotlin·android jetpack
AirDroid_cn4 小时前
OPPO手机怎样被其他手机远程控制?两台OPPO手机如何相互远程控制?
android·windows·ios·智能手机·iphone·远程工作·远程控制
尊治4 小时前
手机电工仿真软件更新了
android
xiangzhihong87 小时前
使用Universal Links与Android App Links实现网页无缝跳转至应用
android·ios
车载应用猿8 小时前
基于Android14的CarService 启动流程分析
android
没有了遇见9 小时前
Android 渐变色实现总结
android
雨白11 小时前
Jetpack系列(四):精通WorkManager,让后台任务不再失控
android·android jetpack
mmoyula13 小时前
【RK3568 驱动开发:实现一个最基础的网络设备】
android·linux·驱动开发
sam.li14 小时前
WebView安全实现(一)
android·安全·webview
移动开发者1号15 小时前
Kotlin协程超时控制:深入理解withTimeout与withTimeoutOrNull
android·kotlin