我正在try 理解如何使用保存可以传递给不同屏幕的值的ViewModel.
我已经编写了一个非常简单的程序来try 理解这个概念.
以下是我的主要活动:
sealed class Destination(val route: String) {
object PlayerSelection: Destination("PlayerSelection")
object TwoPlayerGame: Destination("TwoPlayerGame")
object ThreePlayerGame: Destination("ThreePlayerGame")
object FourPlayerGame: Destination("FourPlayerGame")
}
class MainActivity : ComponentActivity() {
private val viewModel: MainViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Viewmodels_and_NavigationTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
ScreenSetup(viewModel)
}
}
}
}
}
以下是我的NavigationApphost:
@Composable
fun NavigationAppHost (navController: NavController, viewModel: MainViewModel) {
NavHost(navController = navController as NavHostController, startDestination = "PlayerSelection") {
composable(Destination.PlayerSelection.route) { PlayerSelection(navController,MainViewModel()) }
composable(Destination.TwoPlayerGame.route) {TwoPlayerGame(navController,MainViewModel())}
composable(Destination.ThreePlayerGame.route) {ThreePlayerGame(navController,MainViewModel())}
composable(Destination.FourPlayerGame.route) {FourPlayerGame(navController,MainViewModel())}
}
}
下面是我的ScreenSetup:
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ScreenSetup(viewModel: MainViewModel) {
//Navigation Stuff
val navController = rememberNavController()
Scaffold(
topBar = { TopAppBar(title = { Text(text = "Viewmodels and Navigation") }) },
content = { padding ->
Column(Modifier.padding(padding)) {
NavigationAppHost(navController = navController,viewModel)
}
},
bottomBar = { Text(text = "BottomBar") }
)
}
以下是Composable PlayerSelection:
@Composable
fun PlayerSelection(navController: NavController, viewModel: MainViewModel) {
val HowManyPlayers: Int by viewModel.howManyPlayers.collectAsState()
Column {
Row {
Text(text = "How Many Players?")
}
Row() {
Button(onClick = { viewModel.Selection(2) }) {
Text("Two Players")
}
Button(onClick = { viewModel.Selection(3) }) {
Text("Three Players")
}
Button(onClick = { viewModel.Selection(4) }) {
Text("Four Players")
}
}
Row() {
Text(text = "Current Value Held in MainViewModel = ${HowManyPlayers}")
}
Button(onClick = {
if (HowManyPlayers == 2) {
navController.navigate(Destination.TwoPlayerGame.route)
}
if (HowManyPlayers == 3) {
navController.navigate(Destination.ThreePlayerGame.route)
}
if (HowManyPlayers == 4) {
navController.navigate(Destination.FourPlayerGame.route)
}
}) {
Text(text = "Click To Navigate To Next Screen")
}
}
}
以下是MainViewModel:
class MainViewModel : ViewModel() {
var _howManyPlayers = MutableStateFlow(0)
var howManyPlayers = _howManyPlayers.asStateFlow()
fun Selection(players:Int) {
_howManyPlayers.value = players
}
}
下面是TwoPlayerGame Composable:
@Composable
fun TwoPlayerGame(navController: NavController, viewModel: MainViewModel) {
val howManyPlayers by viewModel.howManyPlayers.collectAsState()
Column {
Row(Modifier.padding(50.dp)) {
Text(text = "Two Player Game")
}
Row {
Text(text = "Value of howManyPlayers in viewmodel = ${howManyPlayers}")
}
}
}
当用户在PlayerSelection屏幕中 Select 有多少玩家时,MainViewModel内的HowManyPlayers变量会因用户按下哪个按钮而成功更改.我可以看到这条线很管用:
Text(text = "Current Value Held in MainViewModel = ${HowManyPlayers}")
个
这真是太酷了.但是,当我单击按钮导航到TwoPlayerGame时,MainViewModel中的变量HowManyPlayers再次重置为0.为什么在导航到新屏幕时,MainViewModel中的HowManyPlayers值重置为0?有没有一种方法可以将一个ViewModel传递给不同的屏幕,同时在传递的ViewModel中保留变量值?
谢谢你考虑我的问题,我真的很感激!