gpt4 book ai didi

android - Room 分页无法正确地将 Flow> 与其他流合并

转载 作者:行者123 更新时间:2023-12-05 00:18:29 25 4
gpt4 key购买 nike

我正在尝试使用Paging 3图书馆获取Flow<PagingData<Scan>>来自Room ,然后检查是否在 recyclerview 中选择了项目,因此我将此类映射到另一个名为 ScanMapper 的类。为了实现此映射,每当用户将某个项目标记为选定时,我都会更新 Map里面 MutableStateFlow<Map<Int, State>> 。这里是Map查找 Index(Int)获取 State , State只是一个 enum代表状态的类 UNINITIALISED , USELECTEDSELECTED .

我将 map 的值设置为 StateFlow<Map<Int,State>> 。问题是,我试图结合 Flow<PagingData<Scan>>StateFlow<Map<Int,State>>为了也通过 State作为 ScanMapper 的参数自此上课State取自StateFlow<Map<Int,State>>并且不是原始 Scan 的一部分类(class)。但是PagingDataAdapter似乎总是得到 State UNINITIALISED尽管当我将项目标记为在项目上选择时,单击使用 markSelected(scanId: Int)功能。

请告诉我我在这里缺少什么。

更新

我能够通过使用 Flow<List<Scan>> 实现我想要的功能并删除 Paging 3 的使用使用带有 DiffUtils 的回收器适配器的库。尽管这不是实际的解决方案,因为它消除了 pagination using paging 3库,但以下更改允许我执行项目选择:

更新了 Dao

@Query("SELECT * FROM scan ORDER BY timeOfStorage DESC")
fun getAllScansList(): Flow<List<Scan>>

更新了 ViewModel 中的函数

fun getData(context: Context): Flow<List<ScanMapper>> {

val dao = ScanDatabase.invoke(context).getScanDao()

return combine(
dao.getAllScansList(),
myMap
) { scan, stateMap ->
scan.map {
it.toScanMapper(stateMap[it.id] ?: State.UNKNOWN)
}
}.flatMapLatest {
flow {
emit(it)
}
}
}

更新了 fragment 代码

mainViewModel.getData(requireContext()).collect {

adapter.asyncListDiffer.submitList(it as MutableList)
}

原始问题

我的扫描类(class):

@Entity(tableName = "scan")
@Parcelize
data class Scan (
@PrimaryKey(autoGenerate = true)
var id: Int = 0,
val name: String,
val recognisedText: String,
val timeOfStorage: Long,
val filename: String
): Parcelable {

}

我的 ScanMapper 类:

data class ScanMapper(
val id: Int,
val name: String,
val recognisedText: String,
val timeOfStorage: Long,
val filename: String,
val isSelected: State
)

enum class State{
UNINITIALISED,
SELECTED,
UNSELECTED,
UNKNOWN
}

扫描到 ScanMapper 的转换器,反之亦然

fun ScanMapper.mapToScan() =
Scan(
id = id,
name = name,
recognisedText = recognisedText,
timeOfStorage = timeOfStorage,
filename = filename
)

fun Scan.toScanMapper(isSelected: State) =
ScanMapper(
id = id,
name = name,
recognisedText = recognisedText,
timeOfStorage = timeOfStorage,
filename = filename,
isSelected = isSelected
)

Dao 中的我的 PagingSource

@Query("SELECT * FROM scan ORDER BY timeOfStorage DESC")
fun getAllScans(): PagingSource<Int,Scan>

@Query("SELECT id FROM scan")
fun getAllIds(): List<Int>

使用 getScansFlow() 获取流量

fun getScansFlow(context: Context): Flow<PagingData<Scan>> {

val scanDao = ScanDatabase.invoke(context).getScanDao()

return Pager(
config = PagingConfig(
pageSize = 10,
maxSize = 30,
enablePlaceholders = false
),
pagingSourceFactory = { scanDao.getAllScans() }
).flow.cachedIn(viewModelScope)

}

初始化房间中存在的 ID 的 map

fun initList() =
viewModelScope.launch {

var idList: List<Int> = listOf()

withContext(Dispatchers.IO) {

val task = async {
return@async ScanDatabase.invoke(context).getScanDao().getAllIds()
}
idList = task.await()
}

val map = _myMap.value.toMutableMap()

for (id in idList) {
map[id] = State.UNINITIALISED
}

_myMap.value = map

}

ViewModel 中获取流程并将其组合的函数

    fun getScansSyncFlow(context: Context) {

viewModelScope.launch {

combine(
getScansFlow(context),
myMap
) { scan, stateMap ->
scan.map {
it.toScanMapper(stateMap[it.id] ?: State.UNKNOWN)
}
}.collect{
_myFlow.emit(it)
}
}
}

myFlowStateFlow<PagingData<ScanMapper>?> .

这就是我更新 Map 的方式当用户在 recyclerview 中选择某个项目时。

fun markSelected(scanId: Int) {

val map = _myMap.value.toMutableMap()
map[scanId] = State.SELECTED
_myMap.value = map
}

那么,我正在收集这个myFlow在我的fragment像这样:

lifecycleScope.launchWhenStarted {

mainViewModel.getScansSyncFlow(requireContext())

mainViewModel.myFlow.collect { data ->

data?.let {

adapter.submitData(it)
}
}
}

最佳答案

我看到的直接问题是您使用的是collect 而不是collectLatest。由于 SubmitData 不会返回,因此您将永远不会收到来自 Flow 的更新。

mainViewModel.myFlow.collectLatest {
adapter.submitData(it)
}

关于android - Room 分页无法正确地将 Flow<PagingData<Model>> 与其他流合并,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67495592/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com