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

使用PagingData<T>.insertSeparators插入的首个头部项返回后消失问题

问题

开发简易备忘录应用时,采用Jetpack Compose的LazyColumn结合Paging 3库展示备忘录列表,通过PagingData<T>.insertSeparators方法添加日期分组头部。该功能初始显示正常,但导航至备忘录详情页后返回列表页时,首个日期头部项会消失。

核心分隔符生成代码:

private fun insertDateSeparators(listThanksRecordUiModels: PagingData<ListThanksRecordUiState.ThanksRecordItemWithImages>) =
    listThanksRecordUiModels.insertSeparators { before: ListThanksRecordUiState.ThanksRecordItemWithImages?, after: ListThanksRecordUiState.ThanksRecordItemWithImages? ->
        createDateHeaderSeparatorsIfNeedTo(after, before)
    }

private fun createDateHeaderSeparatorsIfNeedTo(
    after: ListThanksRecordUiState.ThanksRecordItemWithImages?,
    before: ListThanksRecordUiState.ThanksRecordItemWithImages?
): ListThanksRecordUiState.DateHeaderItem? {
    after ?: return null
    before ?: return ListThanksRecordUiState.DateHeaderItem(after.thanksRecordWithImages.thanksRecord.date)

    return if (before.thanksRecordWithImages.thanksRecord.date != after.thanksRecordWithImages.thanksRecord.date) {
        ListThanksRecordUiState.DateHeaderItem(after.thanksRecordWithImages.thanksRecord.date)
    } else {
        null
    }
}

完整ViewModel代码:

@HiltViewModel
class ListThanksViewModel @Inject constructor(
    getThanksRecordWitImagesPagingDataFlow: GetThanksRecordWithImagesPagingDataFlowUseCase,
    @IoDispatcher private val ioDispatcher: CoroutineDispatcher
) : ViewModel() {

    private val _thanksRecordsPagingData = MutableStateFlow<PagingData<ListThanksRecordUiState>>(PagingData.empty())
    val thanksRecordsPagingData: StateFlow<PagingData<ListThanksRecordUiState>> = _thanksRecordsPagingData

    init {
        viewModelScope.launch {
            getThanksRecordWitImagesPagingDataFlow()
                .cachedIn(viewModelScope + ioDispatcher)
                .collectLatest { pagingData ->
                    _thanksRecordsPagingData.update { insertDateSeparators(mapToUiModels(pagingData)) }
                }
        }
    }

    private fun mapToUiModels(pagingData: PagingData<ThanksRecordWithImages>) =
        pagingData.map { thanksRecord ->
            ListThanksRecordUiState.ThanksRecordItemWithImages(thanksRecord)
        }

    private fun insertDateSeparators(listThanksRecordUiModels: PagingData<ListThanksRecordUiState.ThanksRecordItemWithImages>) =
        listThanksRecordUiModels.insertSeparators { before: ListThanksRecordUiState.ThanksRecordItemWithImages?, after: ListThanksRecordUiState.ThanksRecordItemWithImages? ->
            createDateHeaderSeparatorsIfNeedTo(after, before)
        }

    private fun createDateHeaderSeparatorsIfNeedTo(
        after: ListThanksRecordUiState.ThanksRecordItemWithImages?,
        before: ListThanksRecordUiState.ThanksRecordItemWithImages?
    ): ListThanksRecordUiState.DateHeaderItem? {
        after ?: return null
        before ?: return ListThanksRecordUiState.DateHeaderItem(after.thanksRecordWithImages.thanksRecord.date)

        return if (before.thanksRecordWithImages.thanksRecord.date != after.thanksRecordWithImages.thanksRecord.date) {
            ListThanksRecordUiState.DateHeaderItem(after.thanksRecordWithImages.thanksRecord.date)
        } else {
            null
        }
    }
}
解决方案

问题根源在于**cachedIn方法的错误调用**:
cachedIn(viewModelScope + ioDispatcher)是错误用法,cachedIn仅需传入CoroutineScope,额外拼接调度器会导致分页缓存状态异常,返回列表页时无法正确重建首个日期头部。

修复步骤

  1. 修正cachedIn调用:
    将cachedIn(viewModelScope + ioDispatcher)改为cachedIn(viewModelScope),cachedIn内部会自动处理合适的调度逻辑,无需额外指定。

修改后的ViewModel初始化代码:

init {
    viewModelScope.launch {
        getThanksRecordWitImagesPagingDataFlow()
            .cachedIn(viewModelScope) // 修正此处
            .collectLatest { pagingData ->
                _thanksRecordsPagingData.update { insertDateSeparators(mapToUiModels(pagingData)) }
            }
    }
}

额外排查点(若修复后仍有问题)

  • 确保ListThanksRecordUiState的所有子类正确实现equals和hashCode方法,Paging依赖这些方法判断数据是否需要更新。
  • 导航返回时,通过日志确认collectLatest是否收到新的分页数据,排查是否存在数据未刷新的情况。

内容的提问来源于stack exchange,提问作者박찬준

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 19:53:09