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: [androidx.compose.runtime.PausableMonotonicFrameClock@186f44, StandaloneCoroutine{Cancelling}@ee6482d, AndroidUiDispatcher@1d8a162]