我目前正在按照 docs 测试撰写导航。考虑有两个屏幕,分别称为 Home 和 Web。导航使用如下:
@Composable
fun ButtonNavigationApp() {
val navController = rememberNavController()
Scaffold(
bottomBar = { BottomNavigationBar(navController) }
) { innerPadding ->
NavHost(
navController = navController,
startDestination = "Home"
) {
addHomeScreen()
addWebScreen()
}
}
}
主屏幕:
fun NavGraphBuilder.addHomeScreen() {
composable("Home") {
Text("Home is here")
}
}
网页屏幕:
fun NavGraphBuilder.addWebScreen() {
composable("Web") {
AndroidView(
onReset = {}, // Add to reuse the view as documentation says.
factory = { context ->
WebView(context).apply {
// Initializing web-view here
}
},
update = { it.loadUrl("google.com") }
)
}
}
导航栏:
@Composable
fun BottomNavigationBar(navController: NavHostController) {
...
NavigationBar {
NavigationBarItem(
...
onclick = {
navController.navigate("Home") {
popUpTo(navController.graph.startDestinationId) { saveState = true }
launchSingleTop = true
restoreState = true
}
}
...
)
NavigationBarItem(
...
onclick = {
navController.navigate("Web") {
popUpTo(navController.graph.startDestinationId) { saveState = true }
launchSingleTop = true
restoreState = true
}
}
...
)
}
}
问题:从 Home 导航到 Web 屏幕时,URL 按预期加载。单击 Home,然后单击 Web 时,将再次加载 url(尽管视图模型仍然存在)。
我检查并发现撰写屏幕正在重新创建,因此网络视图再次重新创建。如何强制导航不创建 Web 视图的另一个实例?
您遇到的问题源于使用 popUpTo 导航选项,这会导致 Web 屏幕的可组合项在您每次导航到它时被破坏并重新创建。这会导致 WebView 重新初始化并重新加载 URL。
从导航操作中删除 popUpTo
在 BottomNavigationBar 中,从 navController.navigate 调用中删除 popUpTo 选项:
NavigationBarItem(
...
onClick = {
navController.navigate("Web") {
launchSingleTop = true
restoreState = true
}
}
...
)
对“主页”导航执行相同操作:
NavigationBarItem(
...
onClick = {
navController.navigate("Home") {
launchSingleTop = true
restoreState = true
}
}
...
)
使用remember保留WebView实例
在 addWebScreen 函数中,使用记住在重组中保留 WebView 实例:
fun NavGraphBuilder.addWebScreen() {
composable("Web") {
val context = LocalContext.current
val webView = remember { WebView(context) }
DisposableEffect(Unit) {
onDispose {
webView.destroy()
}
}
AndroidView(
factory = { webView },
update = {
if (webView.url == null) {
webView.loadUrl("https://www.google.com")
}
}
)
}
}
避免弹出返回堆栈:通过不使用 popUpTo,Web 可组合项保留在导航堆栈中,保留其状态。 使用记住:这可以使 WebView 在重组过程中保持活动状态,从而防止它重新加载 URL。 正确的清理:DisposableEffect 确保当可组合项离开组合时 WebView 被销毁,从而避免内存泄漏。