由于被NavHost(会为每个导航目标创建NavBackStackEntry
从而导致不同的生命周期和作用域)包裹后Composable页面无法通过viewModel()得到Activity中的相同实例,所以使用CompositionLocalOf显式传递。
由于NavBackStackEntry每个composeable页面有独立的作用域,所以无法得到Activity的viewModel实例,才需要用到compositionLocalOf向下传递。如果不使用navigation的NavHost,则可以在所有Composable页面/组件直接使用val viewmodel : CustomViewModel = viewModel()
得到相同的viewModel实例。
val localNavController = compositionLocalOf <NavController> { error("No NavController found!") }
val localViewModel = compositionLocalOf <CustomViewModel>{ error("No NavController found!") }
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
val viewmodel : CustomViewModel = viewModel()
CustomThemeComponent(viewmodel.theme) {
val navController = rememberNavController()
CompositionLocalProvider(localNavController provides navController, localViewModel provides viewmodel) {
NavHost(navController = navController, startDestination = "home", enterTransition = {
EnterTransition.None
}, exitTransition = {
ExitTransition.None
}, popEnterTransition = {
EnterTransition.None
}) {
composable("home") {
Button(modifier = Modifier.padding(vertical = 200.dp),onClick = {
viewmodel.theme = when(viewmodel.theme) {
CustomTheme.Themes.LIGHT -> CustomTheme.Themes.DARK
CustomTheme.Themes.DARK -> CustomTheme.Themes.LIGHT
}
}) { Text(text = "切换") }
HomeScreen()
}
composable("profile") {
ProfileScreen()
}
composable("login") {
Login()
}
}
}
}
}
}
}
@Composable
fun HomeScreen() {
val nav = localNavController.current
val viewmodel : CustomViewModel = localViewModel.current
var i1 by rememberSaveable { mutableStateOf("") }
Column(modifier = Modifier.windowInsetsPadding(WindowInsets.systemBars).background(color = CustomTheme.colors.bgColor)) {
Text("首页", color = CustomTheme.colors.textColor, fontWeight = FontWeight.Bold)
TextField(value = i1, onValueChange = { i1 = it }, modifier = Modifier.clip(RoundedCornerShape(CustomTheme.colors.btnShape)))
Button(onClick = {
// nav.navigate("profile")
}) {
Text("跳转到个人中心")
}
}
}
viewModel.kt
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import com.dmjyb.navtest.ui.theme.CustomTheme
class CustomViewModel : ViewModel() {
var theme by mutableStateOf(CustomTheme.Themes.DARK)
}