【发布时间】:2021-08-28 21:08:28
【问题描述】:
最小的可重现示例,因此屏幕旋转后显示的随机值发生了变化:
package composesandbox
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.compose.viewModel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.util.*
val rnd = Random()
suspend fun loadRandomNumber(): Int {
delay(1000L) //emulating network delay
return rnd.nextInt(1000)
}
class RandomNumberViewModel : ViewModel() {
val num = mutableStateOf(0)
fun reload() {
viewModelScope.launch {
num.value = loadRandomNumber()
}
}
}
@Composable
fun RandomNumberScreen() {
val vm = viewModel<RandomNumberViewModel>()
Column {
LaunchedEffect(Unit) {
vm.reload()
}
Text(text = "Random Number:\n ${vm.num.value}")
}
}
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
RandomNumberScreen()
}
}
}
我希望数据(viewmodel.num)只加载ONCE,尽管屏幕旋转。请解释一下,为什么数据会在轮换时重新加载。
【问题讨论】:
-
如果您只想加载一次数据,为什么不在 ViewModel 的
init中加载它? -
@ianhanniballake,最短的解释是在实际示例中我应该使用某个实体的
id来加载。而在 ViewModel 的init上,这个id尚不为人所知 [它作为 @Composable fun EntityScreen(id: Int) 的参数传递] -
如果您在那里使用 Navigation Compose 和参数,那么这些参数 在构造时通过
SavedStateHandle传递给您的 ViewModel。您在使用导航撰写吗? -
谢谢,伊恩,我在阅读文档时错过了这一点!这解决了问题 - 数据可以加载到 ViewModel.init(args)
标签: android android-jetpack-compose