第一次打开撰写屏幕时,我想调用列表 api 或详细 api 等函数。
我目前正在使用 LaunchEffect(true) 来调用此类函数,但问题是当配置更改(如设备旋转、字体更改、亮/暗模式等)时,它会再次被调用。
由于数据没有更新,只有设计需要改变。 最有效的方法是什么?
为了避免在配置更改时再次触发
LaunchedEffect(true)
,您可以使用 rememberSaveable
或 remember
来存储指示该函数已被调用的标志。
var apiCalled by rememberSaveable { mutableStateOf(false) }
if (!apiCalled) {
LaunchedEffect(true) {
// Call your API here
apiCalled = true
}
}
注:
remember
:存储一个在重组过程中持续存在的标志,但不会在进程死亡或状态破坏过程中持续存在。rememberSaveable
:如果您想在进程死亡或配置更改(如旋转、黑暗模式等)时保留标志。有3种主要方法可以实现这个逻辑
class AbcViewModel : ViewModel() {
fun test() { }
}
@Composable
fun TestComposable() {
val viewModel : AbcViewModel = viewModel()
LaunchedEffect(key1 = true) {
viewModel.test()
}
}
class AbcViewModel : ViewModel() {
fun test() { }
init {
test()
}
}
@Composable
fun TestComposable() {
val viewModel : AbcViewModel = viewModel()
}
这个逻辑有助于解决第一个解决方案的所有缺点。 但这意味着每次我们初始化视图模型时,该函数都会在没有任何条件的情况下被调用,并且无法对此执行任何操作。
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 秒内收集流量,则不会重置,数据将直接恢复。
由于这有点超前,如果您不完全理解它,也可以使用第二个解决方案。