Issue
In my plan, I hope to display Home UI when I run an app first, a user can open Purchase UI by clicking a button on Home UI. And more, Purchase UI will be displayed automatically if the app is expired when I run the app first.
In Code A, navActions.navigateToPurchase()
is invoked in both fun NavGraph(...)
and fun ScreenHome(...)
.
The app will crash if I don’t wrap navActions.navigateToPurchase()
with LaunchedEffect
in fun NavGraph()
, why? You can see Error Logs below.
Code A
@Composable
fun NavGraph(
modifier: Modifier = Modifier,
navController: NavHostController = rememberNavController(),
navActions: NavigationActions = remember(navController) { NavigationActions(navController) },
startDestination: String = RouteDestinations.HOME
) {
val currentNavBackStackEntry by navController.currentBackStackEntryAsState()
val currentRoute = currentNavBackStackEntry?.destination?.route ?: startDestination
NavHost(
navController = navController,
startDestination = startDestination,
modifier = modifier
) {
composable(
RouteDestinations.HOME
) {
if (isAppExpired(LocalContext.current)) {
LaunchedEffect(Unit) {
navActions.navigateToPurchase()
}
} else {
ScreenHome(
navActions = navActions
)
}
}
composable(
RouteDestinations.PURCHASE
) { entry ->
ScreenPurchase(
onBack = { navController.popBackStack() }
)
}
}
}
@Composable
fun ScreenHome(
navActions: NavigationActions
) {
Button(
onClick = { navActions.navigateToPurchase() }
) {
Text("Nav to Purchase")
}
}
class NavigationActions(private val navController: NavHostController) {
fun navigateToHome(){
navController.navigate(RouteDestinations.HOME)
}
fun navigateToPurchase(){
navController.navigate(RouteDestinations.PURCHASE)
}
}
class ActivityMain : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
SoundMeterTheme {
Surface(color = MaterialTheme.colors.background) {
NavGraph()
}
}
}
}
}
Error Logs
2022-08-01 19:26:54.271 5611-5655/info.dodata.soundmeter E/cr_VariationsUtils: Failed reading seed file "/data/user/0/info.dodata.soundmeter/app_webview/variations_seed": /data/user/0/info.dodata.soundmeter/app_webview/variations_seed (No such file or directory)
2022-08-01 19:26:54.500 5611-5698/info.dodata.soundmeter E/chromium: [ERROR:gl_surface_egl.cc(335)] eglChooseConfig failed with error EGL_SUCCESS
2022-08-01 19:26:55.288 5611-5704/info.dodata.soundmeter E/eglCodecCommon: GoldfishAddressSpaceHostMemoryAllocator: ioctl_ping failed for device_type=5, ret=-1
2022-08-01 19:26:55.510 5611-5698/info.dodata.soundmeter E/chromium: [ERROR:gl_surface_egl.cc(335)] eglChooseConfig failed with error EGL_SUCCESS
2022-08-01 19:26:55.624 5611-5611/info.dodata.soundmeter E/AndroidRuntime: FATAL EXCEPTION: main
Process: info.dodata.soundmeter, PID: 5611
java.util.NoSuchElementException: List contains no element matching the predicate.
at androidx.navigation.compose.NavHostKt$NavHost$4.invoke(NavHost.kt:180)
at androidx.navigation.compose.NavHostKt$NavHost$4.invoke(NavHost.kt:141)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:116)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.animation.CrossfadeKt$Crossfade$4$1.invoke(Crossfade.kt:115)
at androidx.compose.animation.CrossfadeKt$Crossfade$4$1.invoke(Crossfade.kt:110)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.animation.CrossfadeKt.Crossfade(Crossfade.kt:124)
at androidx.compose.animation.CrossfadeKt.Crossfade(Crossfade.kt:55)
at androidx.navigation.compose.NavHostKt.NavHost(NavHost.kt:141)
at androidx.navigation.compose.NavHostKt.NavHost(NavHost.kt:67)
at info.dodata.soundmeter.presentation.ui.NavGraphKt.NavGraph(NavGraph.kt:38)
at info.dodata.soundmeter.presentation.ui.NavGraphKt$NavGraph$3.invoke(Unknown Source:21)
at info.dodata.soundmeter.presentation.ui.NavGraphKt$NavGraph$3.invoke(Unknown Source:10)
at androidx.compose.runtime.RecomposeScopeImpl.compose(RecomposeScopeImpl.kt:157)
at androidx.compose.runtime.ComposerImpl.recomposeToGroupEnd(Composer.kt:2270)
at androidx.compose.runtime.ComposerImpl.skipCurrentGroup(Composer.kt:2530)
at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:3038)
at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:3024)
at androidx.compose.runtime.SnapshotStateKt__DerivedStateKt.observeDerivedStateRecalculations(DerivedState.kt:252)
at androidx.compose.runtime.SnapshotStateKt.observeDerivedStateRecalculations(Unknown Source:1)
at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:3024)
at androidx.compose.runtime.ComposerImpl.recompose$runtime_release(Composer.kt:2999)
at androidx.compose.runtime.CompositionImpl.recompose(Composition.kt:709)
at androidx.compose.runtime.Recomposer.performRecompose(Recomposer.kt:876)
at androidx.compose.runtime.Recomposer.access$performRecompose(Recomposer.kt:107)
at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$2.invoke(Recomposer.kt:485)
at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$2.invoke(Recomposer.kt:454)
at androidx.compose.ui.platform.AndroidUiFrameClock$withFrameNanos$2$callback$1.doFrame(AndroidUiFrameClock.android.kt:34)
at androidx.compose.ui.platform.AndroidUiDispatcher.performFrameDispatch(AndroidUiDispatcher.android.kt:109)
at androidx.compose.ui.platform.AndroidUiDispatcher.access$performFrameDispatch(AndroidUiDispatcher.android.kt:41)
at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.doFrame(AndroidUiDispatcher.android.kt:69)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:947)
at android.view.Choreographer.doCallbacks(Choreographer.java:761)
at android.view.Choreographer.doFrame(Choreographer.java:693)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:935)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
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: [[email protected], StandaloneCoroutine{Cancelling}@ee6482d, [email protected]]
Solution
for my simple knowledge, the navigate function need to be called in the function or click event, navActions.navigateToPurchase() was not called in any of the above, because function marked Composable is not like normal function or click event, that is why LauchEffect is used as side effect for such scenarios as explained by jetpack compose tutorials on google developer guide
Answered By – masokaya
This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0