You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Paging 3水平滚动RecyclerView一次性加载所有页面问题

Android Paging 3 水平滚动RecyclerView一次性加载所有页面问题

我在使用Android Paging 3库时遇到了一次性加载所有页面的问题,当前场景中RecyclerView没有嵌套在任何可无限滚动的容器(如NestedScrollView)中,仅直接作为ConstraintLayout的子控件,且为水平滚动模式。尝试了多种方案都无法解决,甚至考虑放弃使用该API退回原有实现,相关代码示例如下:

布局文件代码

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/clDashboardMain"
    android:background="@color/white"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginBottom="@dimen/spacing_24"
        android:clipToPadding="false"
        android:orientation="horizontal"
        android:paddingStart="@dimen/spacing_24"
        android:paddingEnd="@dimen/spacing_24"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

MyRepository代码

override fun getData(latitude: Double, longitude: Double): LiveData<PagingData<DataPost>> {
      return Pager(
             config = PagingConfig(
                     pageSize = NETWORK_PAGE_SIZE, // 取值为20
                     enablePlaceholders = false
             ),
             pagingSourceFactory = {
                 GetPagingSource(myApiService = myApiService, latitude = latitude, longitude = longitude)
             }
     ).liveData
 }

PagingSource文件代码

private const val INITIAL_LOAD_SIZE = 1

class GetPagingSource(
        private val myApiService: MyApiService,
        private val latitude: Double,
        private val longitude: Double
        ) : PagingSource<Int, DataPost>() {
    override suspend fun load(params: LoadParams<Int>): LoadResult<Int, DataPost> {

        // Retrofit调用遇到网络问题会抛出IOException,非2xx状态码会抛出HttpException
        return try {
            // 刷新时key可能为null,此处默认从第1页开始加载,后端接口页码从0开始索引
            val pageNumber = params.key ?: INITIAL_LOAD_SIZE

            // Retrofit协程CallAdapter自动调度到工作线程,无需手动切IO线程
            val response = myApiService.getData(latitude = latitude, longitude = longitude, page= pageNumber)

            // 第一页没有上一页,返回null标记没有前置页面
            val prevKey = if (pageNumber == INITIAL_LOAD_SIZE) null else pageNumber - 1

            // 接口返回空列表说明没有更多数据,返回null标记没有后续页面
            val nextKey = if (response.data.isNotEmpty()) pageNumber + 1 else null
            LoadResult.Page(
                    data = response.data.filter { it.coordinates.longitude > 0.0 },
                    prevKey = prevKey,
                    nextKey = nextKey
            )
        } catch (e: IOException) {
            LoadResult.Error(e)
        } catch (e: HttpException) {
            LoadResult.Error(e)
        }
    }

    override fun getRefreshKey(state: PagingState<Int, DataPost>): Int? {
        return state.anchorPosition?.let {
            state.closestPageToPosition(it)?.prevKey?.plus(1)
                    ?: state.closestPageToPosition(it)?.nextKey?.minus(1)
        }
    }
}

ViewModel代码

// LiveData用例
fun getData(latitude: Double, longitude: Double): LiveData<PagingData<DataPostUIWrapper>> {
    val currentLoggedUser = profileContract.getUserProfileId()

    return postsContract.getPublicPosts(latitude, longitude)
            .map {
                it.map { dataPost ->
                    DataPostUIWrapper(dataPost, dataPost.isLikedBy(currentLoggedUser))
                }
            }
            .cachedIn(viewModelScope)
}

UI层观察代码

viewModel.getData(latitude = userLocation.latitude, longitude = userLocation.longitude).observe(viewLifecycleOwner, {
    lifecycleScope.launch {
        myAdapter.submitData(it)
    }
})

内容的提问来源于stack exchange,提问作者DM developing

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.11 16:39:03