You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Room @Transaction未按预期工作:Flow在事务中间触发

Room事务中Flow提前触发数据发射的问题

我在Room DAO中定义了带@Transaction注解的refreshInboxMessages方法,逻辑是先执行deleteAll再执行insertAll,但发现getAllFlow会在deleteAll完成、insertAll执行前发射空列表,而非等整个事务完成后再发射数据。我尝试过用@Transaction注解,也试过runInTransaction{},都没能解决这个问题。

我的DAO代码如下:

private const val RECENT_UPDATE_THRESHOLD_MS = 60_000L

@Dao
interface InboxMessageDao {
    @Query(
        "SELECT * FROM inbox_message " +
                "WHERE toEmail == (SELECT email FROM email_address WHERE isCurrent = 1) " +
                "AND (strftime('%s', 'now') * 1000 - cacheLastUpdate) < $RECENT_UPDATE_THRESHOLD_MS"
    )
    fun getAllFlow(): Flow<List<InboxMessageEntity>>

    @Insert
    suspend fun insertAll(messages: List<InboxMessageEntity>)

    @Query("DELETE FROM inbox_message")
    suspend fun deleteAll()

    @Query("SELECT cacheLastUpdate FROM inbox_message WHERE toEmail == :toEmail LIMIT 1")
    suspend fun getCacheLastUpdate(toEmail: String): Long?

    @Transaction // TODO: This fails tests sometimes, why?
    suspend fun refreshInboxMessages(newMessages: List<InboxMessageEntity>) {
        deleteAll()
        // Flow seems to be propagated here giving me sometimes empty list in androidTests
        insertAll(newMessages)
    }
}

我期望Flow能在整个事务执行完成后再发射数据。

附上我的Android测试用例:

@Test
fun shouldPropagateOneMessage() = runTest {
        // given
        coEvery { repository.getInboxMessagesFromApi() } returns listOf(inboxMessage)

        val viewModel = InboxMessageViewModel(StandardTestDispatcher(testScheduler))
        advanceUntilIdle()

        // expect
        val result = viewModel.uiState.first()
        advanceUntilIdle()

assertThat(result).isEqualTo(ViewModelState.Success(listOf(inboxMessage)))
}

测试偶尔会失败,原因是Flow发射了空列表,导致ViewModel触发了ViewModelState.Empty状态。

内容的提问来源于stack exchange,提问作者tomapplause

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 20:22:38