我有一个可组合的小部件,在应用程序进入后台或屏幕在底部导航更改后进入后退堆栈后,它使用 RememberSaveable 来生存。这是小部件的代码:
val banner = bannerViewModel.bannerStateFlow.collectAsStateWithLifecycle(null)
val rememberedBanner = rememberSaveable { banner }
另一方面,小部件使用连接到用例的视图模型,然后连接到存储库来收集信息,这是视图模型中的代码:
@HiltViewModel
internal class BannerViewModel @Inject constructor (
private val savedStateHandle: SavedStateHandle,
private val getBannerUseCase: GetBannerUseCase
): ViewModel() {
@OptIn(ExperimentalCoroutinesApi::class)
val bannerStateFlow = savedStateHandle.getStateFlow<Banner?>(
key = "bannerInfoResourceId",
initialValue = null
).flatMapLatest {
getBannerUseCase()
}
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
initialValue = null
).onStart {
println("bannerFromFlow onStart - ViewModel")
}.onCompletion {
println("bannerFromFlow onCompletion - ViewModel")
}
}
存储库连接到 Firebase 实时数据库数据源并使用流程保持连接,一切正常,您在 Firebase 中更改值,我会立即在 UI 上看到该更改。但是,一旦我导航其他应用程序的部分,然后返回到此小部件,UI 就会从保存的状态恢复(您可以看到小部件没有重新组合),但 Firebase 中更改的新值不再在 UI 中更新。我调试了流程,似乎正在工作并接收新值,就像 CollectAsStateWithLifecycle 不再从流程中收集值一样。
有什么线索吗?
rememberedBanner
保存了State
在初始合成时创建的bannerViewModel.bannerStateFlow.collectAsStateWithLifecycle(null)
并且从不更新它,同时存储在State
中的banner
将在每次重新创建屏幕时更新。
您可能想要的是记住该值,而不是
State
本身。要保持 rememberedBanner
更新,您还应该指定值,更改后将重新初始化 rememberSaveable
状态。
val rememberedBanner = rememberSaveable(banner.value) { banner.value }
尽管如此,这似乎是毫无意义的额外工作。为什么不直接使用
banner.value
?