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

Room返回的Flow使用stateIn无效,改用shareIn却正常工作

问题:使用stateIn时Flow更新不触发UI刷新,换成shareIn则正常

相关代码

DAO代码

@Query("SELECT * FROM reminders")
fun getAll(): Flow<List<ReminderEntity>>

Repository代码

override fun getAllRemindersAsFlow(): Flow<List<Reminder>> {
    return mRemindersDao.getAll().map {
        Log.e("TAG", "room emitting")
        it.map(ReminderEntity::toDomain)
    }
}

ViewModel代码(无法正常工作的两种写法)

第一种写法:

val reminders = mRemindersRepository.getAllRemindersAsFlow().stateIn(
    scope = viewModelScope,
    started = SharingStarted.Eagerly,
    initialValue = emptyList()
)

第二种写法(添加distinctUntilChanged后依然无效):

val reminders = mRemindersRepository.getAllRemindersAsFlow().distinctUntilChanged { old, new -> 
  // old和new相等时返回true
  old == new
}.stateIn(
    scope = viewModelScope,
    started = SharingStarted.Eagerly,
    initialValue = emptyList()
)

Fragment的onViewCreated方法代码

lifecycleScope.launch {
    mViewModel.reminders.collectLatest { reminders ->
        Log.e("TAG", "onViewCreated: Updated")
        when (mBinding.remindersBottomNavigationView.selectedItemId) {
            R.id.upcoming_reminders -> if (reminders.isEmpty()) {
                mBinding.reminderHelpLabel.setText(R.string.no_upcoming_reminder)
            } else mRemindersRecyclerViewAdapter.setReminders(reminders.filter(Reminder::isUpcoming))
            R.id.all_reminders -> if (reminders.isEmpty()) {
                mBinding.reminderHelpLabel.setText(R.string.click_to_create_a_reminder)
            } else mRemindersRecyclerViewAdapter.setReminders(reminders)
        }
    }
}

问题现象

更新提醒时,日志中能看到Room emitting,但onViewCreated: Updated无输出,UI也未更新。

通过日志确认列表确实发生了变化:

  • 更新前Room输出:
room emitting: ReminderEntity(id=8, title=Test, time=[1035, 1165], days=[Tue], enabled=false)
room emitting: ReminderEntity(id=9, title=Test, time=[1040, 1115, 1110], days=[Sun, Mon, Tue, Wed, Thu, Fri, Sat], enabled=true)
room emitting: ReminderEntity(id=17, title=yui, time=[1415], days=[Sun, Mon, Tue, Wed, Thu, Fri, Sat], enabled=true)
  • 禁用一个提醒后Room输出:
room emitting: ReminderEntity(id=8, title=Test, time=[1035, 1165], days=[Tue], enabled=false)
room emitting: ReminderEntity(id=9, title=Test, time=[1040, 1115, 1110], days=[Sun, Mon, Tue, Wed, Thu, Fri, Sat], enabled=true)
room emitting: ReminderEntity(id=17, title=yui, time=[1415], days=[Sun, Mon, Tue, Wed, Thu, Fri, Sat], enabled=false)

可见最后一条提醒的enabled状态已修改,列表内容确实更新。

但将ViewModel代码改为以下形式后,UI能正常响应更新:

val reminders = mRemindersRepository.getAllRemindersAsFlow().shareIn(
    scope = viewModelScope,
    started = SharingStarted.Eagerly,
    replay = 1
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 14:30:03