插入/更新/更新插入时房间流量未发出

问题描述 投票:0回答:1

我遇到的问题是,当对基础数据库表进行更改时,我的 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 层不会收集/显示更新,除非重新启动应用程序。任何指导将不胜感激!

kotlin retrofit android-room kotlin-flow
1个回答
0
投票

您在观察方法中创建的流程在更新数据库后不会发出任何内容。我认为最干净的做法是让您的 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)
    }
© www.soinside.com 2019 - 2024. All rights reserved.