Hello? I am writing a simple memo app.
The app showing list of memo using paging 3 Library and LazyColumn from Jetpack Compose.
To show date of a group of memos, I am using PagingData<T>.insertSeparators
like below.
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
}
}
It works fine, but when I navigate to a detail screen of memo and pop back to list screen, first date header item disappeared life below screen record.
Is there a something I missed?
Full ViewModel Code
@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
}
}
}
Full code repository : https://github.com/ChanJun-Park/SeizeTheDay/blob/master/app/src/main/java/com/jingom/seizetheday/presentation/list/ListThanksViewModel.kt
Why do you collect the paging flow in your ViewModel
and forward the values to MutableStateFlow
? That's wrong. Do it like this:
class ListThanksViewModel {
val thanksRecordsPagingData: Flow<PagingData<ListThanksRecordUiState>> =
getThanksRecordWitImagesPagingDataFlow()
.map { pagingData -> mapToUiModels(pagingData) }
.cachedIn(viewModelScope)
.map { pagingData -> insertDateSeparators(pagingData) }
}
and collect this from compose with collectAsLazyPagingItems()
. Not sure if it will solve your problem, but it's good to get the basics right first. Also:
.cachedIn
viewModelScope + ioDispatcher
doesn't make much sense. If you want to load the pages on ioDispatcher
, this won't do it, it has to be done inside of GetThanksRecordWithImagesPagingDataFlowUseCase
.