Android-Kotlin中Paging Library调用API无响应问题排查
问题:Paging Library未触发API调用
在Android Kotlin项目中使用Paging Library调用API时,API请求并未触发。日志仅打印到Repository层,ProductPagingSource中无任何日志输出,说明load()方法完全没执行。但不使用Paging直接调用该API时可以正常返回数据,问题仅出在Paging的使用场景中。
相关代码
NetworkApi.kt
interface NetworkApi { companion object { const val BASE_URL = "" } @POST("v1/products") @JvmSuppressWildcards suspend fun getProductList( @Body requestBody: Map<String, @JvmSuppressWildcards Any> ): List<CustomSection> }
ProductPagingSource.kt
class ProductPagingSource(private val networkApi: NetworkApi) : PagingSource<Int, CustomSection>() { override fun getRefreshKey(state: PagingState<Int, CustomSection>): Int? { val intKey = state.anchorPosition?.let { anchorPosition -> state.closestPageToPosition(anchorPosition)?.prevKey?.plus(1) ?: state.closestPageToPosition(anchorPosition)?.nextKey?.minus(1) } Timber.d("PRODUCT RESPOSNSE SOURCE $intKey") return intKey } override suspend fun load(params: LoadParams<Int>): LoadResult<Int, CustomSection> { val position = params.key ?: STARTING_PAGE_INDEX // Create JSON body for request with given key val body = mapOf( "category" to "115", "user_id" to "", "page" to 1, "order_by" to "null" ) return try { val response = networkApi.getProductList(body) Timber.d("PRODUCT RESPOSNSE SUCCESS $response") LoadResult.Page( data = response, prevKey = if (position == STARTING_PAGE_INDEX) null else position - 1, nextKey = if (response.isEmpty()) null else position + 1 ) } catch (exception: Exception) { Timber.d("PRODUCT RESPOSNSE ERROR ${exception.localizedMessage}") LoadResult.Error(exception) } } }
ProductRepository.kt
class ProductRepository @Inject constructor(val networkApi: NetworkApi) : BaseApiResponse(){ fun getProductList(): Flow<PagingData<CustomSection>> { Timber.d("PRODUCT RESPOSNSE Repository") return Pager(config = PagingConfig(pageSize = 10, prefetchDistance = 10,maxSize = 30, enablePlaceholders = false), pagingSourceFactory = { ProductPagingSource(networkApi) }).flow } }
ProductViewModel.kt(补充内容)
@HiltViewModel class ProductViewModel @Inject constructor(private val productRepository: ProductRepository) : ViewModel() { fun getProductList(): Flow<PagingData<CustomSection>> { Timber.d("PRODUCT RESPOSNSE ViewModel") return productRepository.getProductList() .cachedIn(viewModelScope) } }
Logcat日志
13233-13233 ProductViewModel com.theyoungindians.android2 D PRODUCT RESPOSNSE ViewModel
com.theyoungindians.android2 D PRODUCT RESPOSNSE Repository13233-13233 ProductRepository
解决方案
问题核心是**Flow<PagingData>没有被收集**。Paging的Pager.flow是冷流,只有当有终端操作(比如collect)订阅它时,才会触发PagingSource的load()方法执行,进而调用API。
你需要在UI层(Activity/Fragment)中收集ViewModel返回的Flow,示例如下:
Fragment中收集Flow的示例
class ProductFragment : Fragment() { private val viewModel: ProductViewModel by viewModels() private val adapter = ProductAdapter() // 自定义的PagingDataAdapter override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // 初始化RecyclerView与Adapter recyclerView.adapter = adapter // 收集Flow,触发Paging加载流程 lifecycleScope.launch { viewModel.getProductList().collect { pagingData -> adapter.submitData(pagingData) } } } }
额外检查点:
- 确认已实现
PagingDataAdapter并正确关联RecyclerView - 检查
STARTING_PAGE_INDEX是否已定义(比如设为1),避免position出现异常值 - 确保
PagingConfig的pageSize与API分页逻辑匹配
内容的提问来源于stack exchange,提问作者Pratik Fagadiya
相关产品推荐
相关产品推荐

