打开可组合项时仅调用一次视图模型函数 - Compose Android

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

第一次打开撰写屏幕时,我想调用列表 api 或详细 api 等函数。

我目前正在使用 LaunchEffect(true) 来调用此类函数,但问题是当配置更改(如设备旋转、字体更改、亮/暗模式等)时,它会再次被调用。

由于数据没有更新,只有设计需要改变。 最有效的方法是什么?

android kotlin android-jetpack-compose android-lifecycle
2个回答
0
投票

为了避免在配置更改时再次触发

LaunchedEffect(true)
,您可以使用
rememberSaveable
remember
来存储指示该函数已被调用的标志。

var apiCalled by rememberSaveable { mutableStateOf(false) }

if (!apiCalled) {
    LaunchedEffect(true) {
        // Call your API here
        apiCalled = true
    }
}

注:

  1. remember
    :存储一个在重组过程中持续存在的标志,但不会在进程死亡或状态破坏过程中持续存在。
  2. rememberSaveable
    :如果您想在进程死亡或配置更改(如旋转、黑暗模式等)时保留标志。

0
投票

有3种主要方法可以实现这个逻辑

  1. 最基本的是LaunchEffect(true)
class AbcViewModel : ViewModel() {
    
    fun test() { }

}

@Composable
fun TestComposable() {
    val viewModel : AbcViewModel = viewModel()

    LaunchedEffect(key1 = true) {
        viewModel.test()
    }
}
  1. 使用 viewModel 的 init 块(最可行)
class AbcViewModel : ViewModel() {

    fun test() { }

    init {
        test()
    }

}

@Composable
fun TestComposable() {
    val viewModel : AbcViewModel = viewModel()
}

这个逻辑有助于解决第一个解决方案的所有缺点。 但这意味着每次我们初始化视图模型时,该函数都会在没有任何条件的情况下被调用,并且无法对此执行任何操作。

  1. 使用流量收集(高级)
class AbcViewModel : ViewModel() {

    private val _isLoading = MutableStateFlow(false)
    val isLoading = _isLoading
        .onStart {
            test()
        }
        .stateIn(
            viewModelScope,
            SharingStarted.WhileSubscribed(5.seconds),
            false
        )

    fun test() { }

}

@Composable
fun TestComposable() {
    val viewModel: AbcViewModel = viewModel()
    val loadingState by viewModel.isLoading.collectAsStateWithLifecycle()
}

使用这种方法我们也可以进行调节,这是我们在之前的解决方案中无法做到的。

这里 5 秒是视图模型在重置流程之前等待的时间。因此,如果可组合项在这 5 秒内收集流量,则不会重置,数据将直接恢复。

由于这有点超前,如果您不完全理解它,也可以使用第二个解决方案。

© www.soinside.com 2019 - 2024. All rights reserved.