删除或修改条目状态后无法加载新列表的问题求助
Paging3 删除条目后无法刷新列表的解决方案
我使用Paging3库通过分页从API获取数据,在onViewCreated中能成功加载数据。但调用删除API移除列表条目后,无法将新列表加载到适配器中;重建Fragment后则能正常显示。尝试过likesAdapter?.notifyItemChanged(position)、likesAdapter?.notifyDataSetChanged()以及调用viewModel.getPaginationData()方法,均无效。如何在viewModel.stateDeleteMatch.observe方法中实现正确的刷新效果?
相关代码
LikesFragment.kt
@AndroidEntryPoint class LikesFragment : BaseFragment<FragmentLikesBinding>( bindingInflater = FragmentLikesBinding::inflate ) { private var likesAdapter: LikesAdapter? = null private val viewModel: LikesFragmentViewModel by viewModels() override fun onCreateFinished() { initLikesAdapter() viewModel.getPaginationData() } override fun initObservers() { lifecycleScope.launch { viewModel.pagingData.collect { pagingData -> hideProgress() likesAdapter?.submitData(pagingData) } } viewModel.stateDeleteMatch.observe(viewLifecycleOwner) { state -> state?.let { result -> when (result.isLoading) { false -> { hideProgress() if (result.error != "hata") { result.deletePositionId?.let { position -> // 需要在这里刷新适配器数据 viewModel.getPaginationData() // likesAdapter?.notifyItemChanged(position) } } else { InfoBottomSheetDialog( customMessage = getString(R.string.can_not_delete_now) ).show(childFragmentManager, InfoBottomSheetDialog.TAG) } } true -> showProgress() } } } } }
LikesFragmentViewModel.kt
@HiltViewModel class LikesFragmentViewModel @Inject constructor( private val createUserAnswerUseCase: CreateUserAnswerUseCase, private val deleteMatchUseCase: DeleteMatchUseCase, private val likesPagingSource: LikesPagingSource ) : ViewModel() { var stateCreateUserAnswer = SingleLiveEvent<CreateUserAnswerState>() private set private val _pagingData = MutableStateFlow<PagingData<Likes>>(PagingData.empty()) val pagingData: Flow<PagingData<Likes>> get() = _pagingData private var pageSize = 20 private val pagingConfig = PagingConfig( pageSize = pageSize, enablePlaceholders = false ) fun getPaginationData() { val pager = Pager( config = pagingConfig, pagingSourceFactory = { likesPagingSource } ) // 观察分页数据并更新MutableStateFlow viewModelScope.launch { pager.flow.collectLatest { pagingData -> _pagingData.value = pagingData } } } }
问题根源
- PagingSource复用导致缓存未更新:当前ViewModel复用了同一个
LikesPagingSource实例,Paging3会缓存该数据源的加载结果,即使后端数据已删除,PagingSource未收到失效通知,不会重新请求最新数据。 - StateFlow未触发重新收集:
_pagingData作为StateFlow,若新生成的PagingData与旧数据被判定为逻辑相等,Fragment中的collect不会触发新的submitData调用。
解决方案
方案1:触发PagingSource失效(推荐)
PagingSource默认自带invalidate()方法,调用后会清除缓存并强制重新加载数据。修改ViewModel添加刷新方法:
// LikesFragmentViewModel.kt fun refreshAfterDelete() { // 让现有PagingSource失效,清除缓存 likesPagingSource.invalidate() // 重新加载分页数据 getPaginationData() }
在Fragment的观察者中调用该方法:
// LikesFragment.kt result.deletePositionId?.let { position -> viewModel.refreshAfterDelete() }
方案2:每次创建新的PagingSource实例
调整依赖注入方式,改为注入PagingSource的工厂方法,每次加载都创建新实例,避免缓存复用:
// LikesFragmentViewModel.kt @HiltViewModel class LikesFragmentViewModel @Inject constructor( private val createUserAnswerUseCase: CreateUserAnswerUseCase, private val deleteMatchUseCase: DeleteMatchUseCase, private val likesPagingSourceFactory: () -> LikesPagingSource // 改为工厂注入 ) : ViewModel() { // ... 其他代码不变 fun getPaginationData() { val pager = Pager( config = pagingConfig, pagingSourceFactory = { likesPagingSourceFactory() } // 每次创建新实例 ) viewModelScope.launch { pager.flow.collectLatest { pagingData -> _pagingData.value = pagingData } } } }
之后在Fragment中直接调用viewModel.getPaginationData()即可,新的PagingSource会请求最新数据。
方案3:直接调用适配器的refresh方法
如果你的LikesAdapter继承自PagingDataAdapter,可以直接调用适配器的refresh()方法,内部会自动触发PagingSource失效:
// LikesFragment.kt result.deletePositionId?.let { position -> likesAdapter?.refresh() }
内容的提问来源于stack exchange,提问作者Ahmet Yılmaz
相关产品推荐
相关产品推荐

