Like the following, I add multiple elements to the headerList when needed, and refresh, and the headerList will display as many elements as there are.
val pageFlow = Pager(
config = PagingConfig(
pageSize = PAGE_SIZE,
initialLoadSize = INITIAL_LOAD_SIZE,
enablePlaceholders = false,
prefetchDistance = PREFETCH_DISTANCE,
),
initialKey = 1,
pagingSourceFactory = { HiPagingSourceFactory() }
).flow.map { pagingData ->
headerList.fold(pagingData) { acc, item ->
acc.insertHeaderItem(TerminalSeparatorType.FULLY_COMPLETE, item)
}
}.cachedIn(viewModelScope)
val headerList = mutableListOf<T>()
pagingViewModel.headerList.add(VideoCommentInfo(
videoId = videoId,
userName = user?.userName.toString(),
avatar = user?.avatar.toString(),
content = comment,
createdAt = System.currentTimeMillis() / 1000,
resource = if (filePath == null) null else ResourceInfo(0, filePath),
type = VideoCommentType.TYPE_ROOT
))
adapter.refresh()
But I didn’t want to call the refresh method, so I cached the pagingdata object and called the following method.
lifecycleScope.launch {
pagingViewModel.pageFlow.collect {
adapter.submitPagingData(it)
}
}
adapter.insertHeaderItem(
VideoCommentInfo(
videoId = videoId,
userName = user?.userName.toString(),
avatar = user?.avatar.toString(),
content = comment,
createdAt = System.currentTimeMillis() / 1000,
resource = if (filePath == null) null else ResourceInfo(0, filePath),
type = VideoCommentType.TYPE_ROOT
)
)
var pagingData: PagingData<T>? = null
fun insertHeaderItem(item: T) {
val newPagingData = pagingData?.insertHeaderItem(item = item) ?: return
submitPagingData(newPagingData)
}
fun submitPagingData(pagingData: PagingData<T>) {
this.pagingData = pagingData
if (lifecycleOwner != null) {
submitData(lifecycleOwner.lifecycle, pagingData)
return
}
}
But when I call adapter.insertHeaderItem(VideoCommentInfo() ) method multiple times, only the last piece of data can be displayed.
In fact, I prefer to modify PagingData in the adapter. I don't know why the header cannot be accumulated, so I save the elements that need to be inserted, and submit the full amount to the adapter for each insertion.
private val headerItems = mutableListOf<T>()
fun insertHeaderItem(item: T) {
headerItems.add(0, item)
var newPagingData = pagingData ?: return
headerItems.asReversed().forEach { header ->
newPagingData = newPagingData.insertHeaderItem(item = header)
}
submitPagingData(newPagingData)
}
You can update the headerList
without calling adapter.refresh()
and keep the logic completely in your ViewModel
with only small changes in your code:
private val pageFlow = Pager(...).flow.cachedIn(viewModelScope)
private val headerListFlow = MutableStateFlow(emptyList())
val pageFlowWithHeaders = combine(
pageFlow,
headerListFlow,
) { pagingData, headerList ->
headerList.fold(pagingData) { acc, item ->
acc.insertHeaderItem(item)
}
}
fun addHeader(header: VideoCommentInfo) {
headerListFlow.update { it + header }
}
This makes use of the combine
flow operator to combine the paging flow and flow of the headers. Every time you add new header, new PagingData
are creating without the need to call refresh
and the original paging flow is still cached in your viewModelScope
.