我遇到的问题是,当对基础数据库表进行更改时,我的 Room 数据流不会发出更新。
API服务
interface AtemsService {
@GET("$PATH/data/_apps.json")
suspend fun getPackageData(): Map<String, AtemsPackageInfo>
}
远程实现
class AtemsRemoteImpl @Inject constructor(private val atemsService: AtemsService) : AtemsRemote {
override suspend fun getAtemsPackageData(): Map<String, AtemsPackageInfo> =
atemsService.getPackageData()
}
本地道
@Dao
interface AtemsPackageDao {
@Query("SELECT * FROM $TABLE_NAME")
suspend fun getAll(): List<LocalAtemsPackage>
@Upsert
suspend fun upsertAll(localAtemsPackages: List<LocalAtemsPackage>)
}
回购实施
class AtemsPackageRepositoryImpl @Inject constructor(
private val atemsRemote: AtemsRemote,
private val atemsPackageDao: AtemsPackageDao,
private val atemsPackageMapper: AtemsPackageMapper,
) : AtemsPackageRepository {
override fun observeAtemsPackages(): Flow<List<AtemsPackage>> {
return flow {
val localAtemsPackages = atemsPackageDao.getAll()
emit(atemsPackageMapper.localToDomain(localAtemsPackages))
if (localAtemsPackages.isEmpty()) {
val fetchRemotePackages = atemsRemote.getAtemsPackageData()
val convertToLocal = atemsPackageMapper.remoteToLocal(fetchRemotePackages)
atemsPackageDao.upsertAll(convertToLocal)
}
}
}
}
用例
class AppsUseCaseImpl @Inject constructor(
atemsPackageRepository: AtemsPackageRepository,
) : AppsUseCase {
override val observeApps: Flow<List<AtemsPackage>> = atemsPackageRepository.observeAtemsPackages()
}
查看模型
@HiltViewModel
class SidePanelAppListViewModel @Inject constructor(appsUseCase: AppsUseCase) : ViewModel() {
val apps = appsUseCase.observeApps.stateIn(
scope = viewModelScope,
started = WhileUiSubscribed,
initialValue = emptyList()
)
}
最后; 查看
@Composable
fun SidePanelAppList(
modifier: Modifier = Modifier,
viewModel: SidePanelAppListViewModel = hiltViewModel(),
) {
val apps by viewModel.apps.collectAsStateWithLifecycle()
SidePanelAppList(
modifier = Modifier.then(modifier),
apps = apps
)
}
一切都按预期工作,除了存储库中的方法进行网络调用来检索数据时,尽管已成功将数据保存到 Room 数据库,但我的 ui 层不会收集/显示更新,除非重新启动应用程序。任何指导将不胜感激!
您在观察方法中创建的流程在更新数据库后不会发出任何内容。我认为最干净的做法是让您的 DAO 将列表公开为 Flow,并在需要时使用
onEach
来触发您的获取。
道:
@Dao
interface AtemsPackageDao {
@Query("SELECT * FROM $TABLE_NAME")
fun getAll(): Flow<List<LocalAtemsPackage>>
@Upsert
suspend fun upsertAll(localAtemsPackages: List<LocalAtemsPackage>)
}
在您的回购实施中:
override fun observeAtemsPackages(): Flow<List<AtemsPackage>>
= atemsPackageDao.getAll()
.onEach {
if (it.isEmpty()) {
val fetchRemotePackages = atemsRemote.getAtemsPackageData()
val convertToLocal = atemsPackageMapper.remoteToLocal(fetchRemotePackages)
atemsPackageDao.upsertAll(convertToLocal)
}
}
现在您的流程纯粹返回最新的数据库状态。
onEach
动作是副作用。
如果你可以获取一个空列表,你可能需要做一些事情,这样它只尝试获取一次:
override fun observeAtemsPackages(): Flow<List<AtemsPackage>>
= flow {
val source = atemsPackageDao.getAll()
if (source.first().isEmpty()) {
val fetchRemotePackages = atemsRemote.getAtemsPackageData()
val convertToLocal = atemsPackageMapper.remoteToLocal(fetchRemotePackages)
atemsPackageDao.upsertAll(convertToLocal)
}
emitAll(source)
}