Android Studio Jetpack合成中的导航不断崩溃

flmtquvp  于 2022-11-16  发布在  Android
关注(0)|答案(1)|浏览(165)

我尝试使用Navigation从两个不同的函数访问一个带参数的函数。当我在模拟器中尝试时,应用程序崩溃。应用程序正常构建。
我使用的是compose 1.0.1和navigation 2.5.0
这是导航功能:

@Composable
fun Nav() {

    val navController = rememberNavController()

    NavHost(navController = navController, startDestination = "Main") {
        composable("Main") { Main() }
        composable("Detail/{name}") { backStackEntry ->
            Detail(backStackEntry.arguments?.getString("name").toString())
        }
        composable("Info") { Info(navController) }
        composable("Table") { Table(navController) }
    }
}

这是Main函数,在这里我使用TabRow在屏幕之间导航:

@Composable
fun Main() {
    val tabs = listOf(TabItem.Table, TabItem.Info)
    val tabNum = remember { mutableStateOf(0) }
    
    Scaffold(bottomBar = {
        TabRow(modifier = Modifier.backgroudn(Color.Gray), selectedTabIndex = tabNum.value) {
            tabs.forEachIndexed { index, tab ->
                Tab(text = { Text(tab.title) }, selected = tabNum.value == index, onClick = { tabNum.value = index })
            }
        }
    }) {
        Column(modifier = Modifier.fillMaxHeight()) {
            tabs[tabNum.value].screen()
        }
    }
}

这是TabItem密封类,用于导航:

typealias ComposableFun = @Composable () -> Unit

sealed class TabItem(var title: String, var screen: ComposableFun) {
    object Table : TabItem("Table", { Table(rememberNavController()) })
    object Info : TabItem("Info", { Info(rememberNavController()) })
}

这是Table函数的简短版本:

@Composable
fun Table(navController: NavController) {
    val elements1: List<String> = listOf("H", "Li", "Na", "K", "Rb", "Cs", "Fr")

    Column {
        elements1.forEach { i ->
            Box(modifier = Modifier.size(75.dp).padding(1.dp).clickable(onClick = {
                navController.navigate("Detail/$i")
            })) {
                Canvas(modifier = Modifier.size(75.dp), onDraw = {
                    drawRect(color = Color.Red)
                })
                Text(text = i, fontSize = 30.sp)
            }
        }
    }
}

这是Info函数:

@Composable
fun Info(navController: NavController) {

    val elements: List<String> = listOf("H", "He", "Li", "Be", "B", "C", "N", "O", "F", "Ne", "Na")

    Column {
        elements.forEach { i ->
            Box(modifier = Modifier
                .size(width = 1000.dp, height = 50.dp)
                .padding(5.dp)
                .background(Color.Red)
                .clickable(onClick = {
                    navController.navigate("Detail/$i")
                })) {
                Text(text = text i, fontSize = 30.sp)
            }
        }
    }
}

这是Detail函数的简短版本:

@Composable
fun Detail(name: String) {
    
    Column {
        Box(modifier = Modifier.size(75.dp).padding(1.dp)) {
            Canvas(modifier = Modifier.size(75.dp), onDraw = {
                drawRect(color = Color.Red)
            })
            Text(text = name, fontSize = 30.sp)
        }
    }
}

以下是崩溃日志:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.tavolaperiodica, PID: 8360
    java.lang.NullPointerException
        at androidx.navigation.NavController.navigate(NavController.kt:1652)
        at androidx.navigation.NavController.navigate(NavController.kt:1984)
        at androidx.navigation.NavController.navigate$default(NavController.kt:1979)
        at com.example.tavolaperiodica.TableKt$Table$1$1$1$1$1$1.invoke(Table.kt:50)
        at com.example.tavolaperiodica.TableKt$Table$1$1$1$1$1$1.invoke(Table.kt:49)
        at androidx.compose.foundation.ClickableKt$clickable$4$gesture$1$2.invoke-k-4lQ0M(Clickable.kt:137)
        at androidx.compose.foundation.ClickableKt$clickable$4$gesture$1$2.invoke(Clickable.kt:137)
        at androidx.compose.foundation.gestures.TapGestureDetectorKt$detectTapAndPress$2$1$1.invokeSuspend(TapGestureDetector.kt:378)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:178)
        at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:166)
        at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:397)
        at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl(CancellableContinuationImpl.kt:431)
        at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$default(CancellableContinuationImpl.kt:420)
        at kotlinx.coroutines.CancellableContinuationImpl.resumeWith(CancellableContinuationImpl.kt:328)
        at androidx.compose.ui.input.pointer.SuspendingPointerInputFilter$PointerEventHandlerCoroutine.offerPointerEvent(SuspendingPointerInputFilter.kt:432)
        at androidx.compose.ui.input.pointer.SuspendingPointerInputFilter.dispatchPointerEvent(SuspendingPointerInputFilter.kt:330)
        at androidx.compose.ui.input.pointer.SuspendingPointerInputFilter.onPointerEvent-H0pRuoY(SuspendingPointerInputFilter.kt:343)
        at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:287)
        at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:275)
        at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:275)
        at androidx.compose.ui.input.pointer.NodeParent.dispatchMainEventPass(HitPathTracker.kt:151)
        at androidx.compose.ui.input.pointer.HitPathTracker.dispatchChanges(HitPathTracker.kt:90)
        at androidx.compose.ui.input.pointer.PointerInputEventProcessor.process-gBdvCQM(PointerInputEventProcessor.kt:77)
        at androidx.compose.ui.platform.AndroidComposeView.dispatchTouchEvent(AndroidComposeView.android.kt:860)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3030)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2719)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3030)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2719)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3030)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2719)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3030)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2719)
        at com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:440)
        at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1830)
        at android.app.Activity.dispatchTouchEvent(Activity.java:3400)
        at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:398)
        at android.view.View.dispatchPointerEvent(View.java:12752)
        at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:5106)
        at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4909)
        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4426)
        at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4479)
        at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4445)
        at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4585)
E/AndroidRuntime:     at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4453)
        at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4642)
        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4426)
        at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4479)
        at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4445)
        at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4453)
        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4426)
        at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:7092)
        at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:7061)
        at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:7022)
        at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:7195)
        at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:186)
        at android.os.MessageQueue.nativePollOnce(Native Method)
        at android.os.MessageQueue.next(MessageQueue.java:326)
        at android.os.Looper.loop(Looper.java:160)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
        Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [androidx.compose.runtime.BroadcastFrameClock@3ef7ee, StandaloneCoroutine{Cancelling}@a6e448f, AndroidUiDispatcher@f70f31c]
I/Process: Sending signal. PID: 8360 SIG: 9
zengzsys

zengzsys1#

问题出在您的TabItem密封类别。当建立Table对象和Info对象时,它们会呼叫rememberNavController(),这会导致为您的Activity建立新的NavController执行严修。这表示您正在覆写您在Nav可组合函式中建立的NavController
您应该遵循文档中提到的原则:
您应该在可组合层次结构中所有需要引用它的可组合对象都可以访问它的位置创建NavController。()作为更新屏幕外的可组合对象的真实源。有关此功能的示例,请参阅与底部导航栏集成。
https://developer.android.com/jetpack/compose/navigation#getting-started

相关问题