自学内容网 自学内容网

初始化数据的正确方式?

关于这篇文章

https://proandroiddev.com/loading-initial-data-in-launchedeffect-vs-viewmodel-f1747c20ce62

pl的视频解读

当在viewmodel中需要进行数据的初始化的时候 viewmodel.initData()

放在哪里合适呢,大部分情况下可以放在 viewmodel的init{}模块,但是这样无法指定初始化的时机。

也有人选择在compose的 launchEffect的时候,但是在launcheffect的时候,基本如果界面重新初始化,例如界面旋转这样,那么初始化的数据就会重新又运行一次。

然后就有人指出在demoproject里面的一段代码

val pokemon = savedStateHandle.getStateFlow<Pokemon?>("pokemon", null)
val pokemonInfo: StateFlow<PokemonInfo?> =
  pokemon.filterNotNull().flatMapLatest { pokemon ->
    detailsRepository.fetchPokemonInfo(
      ..
    )
  }.stateIn(
    scope = viewModelScope,
    started = SharingStarted.WhileSubscribed(5_000),
    initialValue = null,
  )

当存在一个冷流(cold flow)提供一些状态值的更新,且这个冷流的创建和/或维护成本很高,但有多个订阅者需要获取最新的状态值。例如,假设状态更新是通过耗费较大成本的网络连接从后端获取的,且需要很长时间来建立连接。

这样我们可以将之前从网络后端费了好大劲获取的pokemonInfo的值

缓存起来,从开始订阅的时候就缓存了,然后直到都没有订阅者了,再过5秒后就清除,如果五秒内重新有订阅者,则不会再去调用后端获取值,而是使用之前缓存的值,如果五秒后,都没有订阅者,当有订阅者重新订阅了,则这个时候,就要重新获取了。

所以在pl的视频后,给出了一种初始化数据的方式就是

 private val _isLoading = MutableStateFlow(false)

    val isLoading = _isLoading
        .onStart { //在开始的时候
            initLoadData()//
        }.stateIn(viewModelScope,
            SharingStarted.WhileSubscribed(5000L),//确保没有订阅者之后,还可以缓存5秒
                false
        )

    fun initLoadData(){
        println("start loading data....")
        viewModelScope.launch {
            _isLoading.value = true
            delay(5000)
            _isLoading.value =false
        }
    }

这样,即便是屏幕旋转,肯定也是再五秒内完成,所以不会造成数据的重新加载


原文地址:https://blog.csdn.net/github_35581409/article/details/142695091

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!