我有一个带有Jetpack Compose的屏幕,它有一个BottomNavigation和一个NavHost。
在某一点上,我将某个值返回到该屏幕,其效果必须是它应该导航到其中一个选项卡。
如果我只使用navController.navigate(destination)
,那么我会出现以下错误:
2022-09-19 13:14:56.577 30826-30826/com.flingtheap E/AndroidRuntime:致命异常:main流程:com.flingtheap,PID:30826java.lang.NullPointerException在androidx.navigation.NavController.anavigation(NavController.kt:1652)在androidx.navigation.NavController.anavigation(NavController.kt:1984)在androidx.navigation.NavControllernavigation$default(NavController.kt:1979)在tech.atlabs.fling.android.core.MainScreenKt.MainScreen(MainScreen.kt:70)在tech.atlabs.fling.android.ComposableSingletons$AppActivityKt$lambda-1$1$6.invoke(AppActivity.kt:66)在tech.atlabs.fling.android.ComposableSingletons$AppActivityKt$lambda-1$1$6.invoke(AppActivity.kt:65)在androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:116)在androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)在androidx.navigation.compose.NavHostKt$NavHost$4$2.ioke(NavHost.kt:163)在androidx.navigation.compose.NavHostKt$NavHost$4$2.ioke(NavHost.kt:162)在androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)在androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)位于androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)位于androidx.compose.runtime.saveable.SaveableStateHolderImpl.SaveableStateProvider(SaveableStateHolder.kt:84)位于androidx.navigation.compose.NavBackStackEntryProviderKt.SaveableStateProvider(NavBackStackEntryProvider.kt:60)位于androidx.navigation.compose.NavBackStackEntryProviderKt.access$SaveableStateProvider(NavBackStackEntryProvider.kt:1)位于androidx.navigation.compose.NavBackStackEntryProviderKt$LocalOwnersProvider$1.ioke(NavBackStackEntryProvider.kt:52)位于androidx.navigation.compose.NavBackStackEntryProviderKt$LocalOwnersProvider$1.ioke(NavBackStackEntryProvider.kt:51)在androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)在androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)位于androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)位于androidx.navigation.compose.NavBackStackEntryProviderKt.LocalOwnersProvider(NavBackStackEntryProvider.kt:47)在androidx.navigation.compose.NavHostKt$NavHost$4.invoke(NavHost.kt:162)在androidx.navigation.compose.NavHostKt$NavHost$4.invoke(NavHost.kt:141)在androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:116)在androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)在androidx.compose.animation.CrosfadeKt$Crosfade$4$1.invoke(Crossfade.kt:115)在androidx.compose.animation.CrosfadeKt$Crosfade$4$1.invoke(Crossfade.kt:110)在androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)在androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)在androidx.compose.animation.CrosfadeKt.Crossfade(Crossfade.kt:124)在androidx.compose.animation.CrosfadeKt.Crossfade(Crossfade.kt:55)在androidx.navigation.compose.NavHostKt.NavHost(NavHost.kt:141)位于androidx.navigation.compose.NavHostKt$NavHost$5.invoke(未知资料来源:13)位于androidx.navigation.compose.NavHostKt$NavHost$5.invoke(未知来源:10)在androidx.compose.runtime.RomposeScopeImpl.compose(RecomposeScopeImpl.kt:145)在androidx.compose.runtime.ComposeImpl.recomposeToGroupEnd(Composer.kt:2363)位于androidx.compose.runtime.ComposerImpl.skipCurrentGroup(Composer.kt:2630)在androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:3217)在androidx.compose.runtime.SComposerImpl$doCompose$2$5.invoke(Composer.kt:3195)在androidx.compose.runtime.SnapshotStateKt_DriverStateKt.observeDerivedStateRecalculations(派生状态kt:336)位于androidx.compose.runtime.SnapshotStateKt.observeDerivedStateRecalculations(未知来源:1)在androidx.compose.runtime.SComposerImpl.doCompose(Composer.kt:3195)2022-09-19 13:14:56.577 30826-30826/com.flingtheap E/AndroidRuntime:在androidx.compose.runtime.ComposerImpl.recompose$runtime_release(Composer.kt:3160)在androidx.compose.runtime.CompositionImpl.recompose(Composition.kt:748)在androidx.compose.runtime.Recomposer.performRecompose(Recomposer.kt:876)在androidx.compose.runtime.Recomposer.access$performRecompose(Recomposer.kt:107)在androidx.compose.runtime.Composer$runRecomposeAndApplyChanges$2.ioke(Recomposer.kt:485)在androidx.compose.runtime.Composer$runRecomposeAndApplyChanges$2.ioke(Recomposer.kt:454)在androidx.compose.ui.platform.AndroidUiFrameClock$withFrameNanos$2$callback$1.doFrame(AndroidUiFFrameClock.android.kt:34)在androidx.compose.ui.platform.AndroidUiDispatcher.performFrameDispatch(AndroidUiDispatcher.android.kt:109)在androidx.compose.ui.platform.AndroidUiDispatcher.access$performFrameDispatch(AndroidUiDispatcher.android.kt:41)在androidx.compose.ui.platform.AndroidUiPadispatchCallback$1.doFrame(AndroidUiPaDispatcher.android.kt:69)在android.view.Cchoreographer$CallbackRecord.run(Choreographer.java:997)在android.view.Cchoreographer.doCallbacks(Choreographer.java:797)位于android.view.Cchoreographer.doFrame(Choreographer.java:728)在android.view.Cchoreographer$FrameDisplayEventReceiver.run(Choreographer.java:984)在android.os.Handler.handleCallback(Handler.java:883)在android.os.Handler.dispatchMessage(Handler.java:100)在android.os.Looper.loop(Looper.java:237)在android.app.ActivityThread.main(ActivityThreads.java:8154)位于java.lang.reflect.Method.ioke(本机方法)网址:com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:496)网址:com.android.internal.os.ZygoteInit.main(ZygoteNit.java:1100)已抑制:kotlin.coroutines.DiagnosticCoroutineContext异常:[androidx.compose.runtime.PausableMonotonicFrameClock@56fece1,androidx.compose.ui.platform.MotionDurationScaleImpl@1da9a06,独立Coroutine{Cancelling}@ba598c7,AndroidUiDispatcher@af8def4]2022-09-19 13:14:56.621 30826-30826/com.flingtheap I/过程:发送信号PID:30826 SIG:9 2022-09-19 13:14:58.738 31683-31683/?E/Zygote:isWhitelistProcess-流程被列入白名单2022-09-1913:14:58.738 31683-31683/?电子邮箱:accessInfo:1 2022-09-1913:14:58.742 31683-31683/?I/com.flingtheap:延迟启用-Xcheck:jni2022-09-19 13:14:58.764 31683-31683/?E/com.flingtheap:未知位在runtime_flags:0x8000 2022-09-19 13:14:58.773 31683-31683/?D/ActivityThread:setConscryptValidator 2022-09-19 13:14:58.77331683-31683/?D/ActivityThread:setConscryptValidator-put 2022-09-1913:15:02.809 31683-31683/com.flingtheap I/FirebaseApp:设备解锁:初始化应用程序的所有Firebase API[DEFAULT]2022-09-19922年2月2日13:15:31683-31683/com.flingtheap I/FirebaseInitProvider:FirebaseApp初始化成功2022-09-19 13:15:03.00031683-31683/com.flingtheap I/[Koin]:[init]声明Android上下文2022-09-19 13:15:03.092 31683-31683/com.flingtheap I/[Koin]:已加载31定义-1.26177 ms 2022-09-19 13:15:03.09231683-31683/com.flingtheap I/[Koin]:创建热切的实例。。。2022-09-19 13:15:08.308 31683-31722/com.flingtheapD/ProfileInstaller:安装com.flingtheap 的配置文件
所以我想这不是正确的方法。
如何使用NavController以编程方式导航?
===
编辑:失败的代码:
const val MAIN_COMPOSABLE_ID=";主";
sealed class MainTabNavigation(
val route: String,
@StringRes val resourceId: Int,
@DrawableRes val drawableId: Int
) {
object Tab1 : MainTabNavigation("tab1", R.string.shop_tabName, R.drawable.tab1)
object Tab2 :
MainTabNavigation("tab2", R.string.wardrobe_tabName, R.drawable.tab2)
object Tab3 : MainTabNavigation("tab3", R.string.cart_tabName, R.drawable.tab3)
object Tab4 : MainTabNavigation("tab4", R.string.profile_tabName, R.drawable.tab4)
}
private val navItems = listOf(
MainTabNavigation.Tab1, MainTabNavigation.Tab2,
MainTabNavigation.Tab3, MainTabNavigation.Tab4
)
@Composable
fun MainScreen(navController: NavController) {
val mainNavController = rememberNavController()
var goToTab2 = false
val commManager by inject<ComposableCommManager>()
val comm = commManager.readComm(MAIN_COMPOSABLE_ID)
comm?.let {
if (it.communication == "go_to_tab2") {
goToTab2 = true
}
}
if (goToTab2) {
// TODO This line fails
mainNavController.navigate(MainTabNavigation.Tab3.route)
}
Scaffold(
modifier = Modifier.systemBarsPadding(),
bottomBar = {
BottomNavigation(
backgroundColor = Color.White,
contentColor = MaterialTheme.colors.primary
) {
val navBackStackEntry by mainNavController.currentBackStackEntryAsState()
val currentDestination = navBackStackEntry?.destination
navItems.forEach { tab ->
BottomNavigationItem(
icon = {
Icon(
painterResource(id = tab.drawableId),
contentDescription = null
)
},
label = { Text(stringResource(tab.resourceId)) },
alwaysShowLabel = false,
selected = currentDestination?.hierarchy?.any { it.route == tab.route } == true,
onClick = {
mainNavController.navigate(tab.route) {
popUpTo(mainNavController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
}
)
}
}
}
) { innerPadding ->
NavHost(
mainNavController,
startDestination = if (goToTab2) {
MainTabNavigation.Tab3.route
} else {
startMainDestination
},
Modifier.padding(innerPadding)
) {
composable(MainTabNavigation.Tab1.route) {
ShopTab(navController)
}
composable(MainTabNavigation.Tab2.route) {
WardrobeTab(navController, mainNavController)
}
composable(MainTabNavigation.Tab3.route) {
CartTab(navController, mainNavController)
}
composable(MainTabNavigation.Tab4.route) {
ProfileTab(navController)
}
}
}
}
if (goToTab2) {
mainNavController.navigate(MainTabNavigation.Tab3.route)
}
在jetpackCompose中,您不能使用这样的代码,因为每次重新编译时,代码都会重新运行。您必须将该部分设置为可点击。或者用";命令读取";以查看模型,并在每个ON_RESUME中检查该值。
或者在ON_RESUME块中读取该值(但viewModel会更好)。
@Composable
fun OnLifecycleEvent(onEvent: (owner: LifecycleOwner, event: Lifecycle.Event) -> Unit) {
val eventHandler = rememberUpdatedState(onEvent)
val lifecycleOwner = rememberUpdatedState(LocalLifecycleOwner.current)
DisposableEffect(lifecycleOwner.value) {
val lifecycle = lifecycleOwner.value.lifecycle
val observer = LifecycleEventObserver { owner, event ->
eventHandler.value(owner, event)
}
lifecycle.addObserver(observer)
onDispose {
lifecycle.removeObserver(observer)
}
}
}
像这样使用
OnLifecycleEvent { _, event ->
when (event) {
Lifecycle.Event.ON_RESUME -> {
mainPageViewModel.setEvent(MainPageContract.Event.OnResume)
}
else -> Unit
}
}