vide
11/22/2023, 7:51 PMLaunchedEffect would always run on the main thread? I have a LauncedEffect calling navigate like this:
LaunchedEffect(key, ...) { navController.navigate(...) { popUpTo(...) } }
And very rarely when running instrumented tests, I get this exception. Am I missing something? Full stack trace in thread.
java.lang.IllegalStateException: Method setCurrentState must be called on the main threadvide
11/22/2023, 7:56 PMjava.lang.IllegalStateException: Method setCurrentState must be called on the main thread
at androidx.lifecycle.LifecycleRegistry.enforceMainThreadIfNeeded(LifecycleRegistry.kt:296)
at androidx.lifecycle.LifecycleRegistry.setCurrentState(LifecycleRegistry.kt:105)
at androidx.navigation.NavBackStackEntry.updateState(NavBackStackEntry.kt:188)
at androidx.navigation.NavBackStackEntry.setMaxLifecycle(NavBackStackEntry.kt:159)
at androidx.navigation.NavController.popEntryFromBackStack(NavController.kt:761)
at androidx.navigation.NavController.access$popEntryFromBackStack(NavController.kt:68)
at androidx.navigation.NavController$executePopOperations$1.invoke(NavController.kt:643)
at androidx.navigation.NavController$executePopOperations$1.invoke(NavController.kt:640)
at androidx.navigation.NavController$NavControllerNavigatorState.pop(NavController.kt:330)
at androidx.navigation.NavigatorState.popWithTransition(NavigatorState.kt:149)
at androidx.navigation.NavController$NavControllerNavigatorState.popWithTransition(NavController.kt:343)
at androidx.navigation.compose.ComposeNavigator.popBackStack(ComposeNavigator.kt:67)
at androidx.navigation.NavController.popBackStackInternal(NavController.kt:280)
at androidx.navigation.NavController.executePopOperations(NavController.kt:640)
at androidx.navigation.NavController.popBackStackInternal(NavController.kt:627)
at androidx.navigation.NavController.navigate(NavController.kt:1837)
at androidx.navigation.NavController.navigate(NavController.kt:1812)
at androidx.navigation.NavController.navigate(NavController.kt:2220)
at androidx.navigation.NavController.navigate$default(NavController.kt:2215)
at androidx.navigation.NavController.navigate(NavController.kt:2200)
at <mypackage>(:19) <- helper functions
at <mypackage>(:17) <- helper functions
at <mypackage>.invokeSuspend(:266) <- in a LaunchedEffect
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at androidx.compose.ui.test.ApplyingContinuationInterceptor$SendApplyContinuation.resumeWith(ApplyingContinuationInterceptor.kt:65)
at androidx.compose.ui.test.FrameDeferringContinuationInterceptor$TrampolinedTask.resume(FrameDeferringContinuationInterceptor.kt:137)
at androidx.compose.ui.test.FrameDeferringContinuationInterceptor.runWithoutResumingCoroutines(FrameDeferringContinuationInterceptor.kt:75)
at androidx.compose.ui.test.TestMonotonicFrameClock.performFrame(TestMonotonicFrameClock.jvm.kt:132)
at androidx.compose.ui.test.TestMonotonicFrameClock.access$performFrame(TestMonotonicFrameClock.jvm.kt:53)
at androidx.compose.ui.test.TestMonotonicFrameClock$withFrameNanos$2$1$2.invokeSuspend(TestMonotonicFrameClock.jvm.kt:110)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:367)
at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:30)
at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable$default(Cancellable.kt:25)
at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:110)
at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:126)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:56)
at kotlinx.coroutines.BuildersKt.launch(Unknown Source:1)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:47)
at kotlinx.coroutines.BuildersKt.launch$default(Unknown Source:1)
at androidx.compose.ui.test.TestMonotonicFrameClock.withFrameNanos(TestMonotonicFrameClock.jvm.kt:108)
at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2.invokeSuspend(Recomposer.kt:548)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at androidx.compose.ui.test.ApplyingContinuationInterceptor$SendApplyContinuation.resumeWith(ApplyingContinuationInterceptor.kt:65)
at androidx.compose.ui.test.FrameDeferringContinuationInterceptor$FrameDeferredContinuation.resumeWith(FrameDeferringContinuationInterceptor.kt:194)
at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:179)
at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:168)
at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:474)
at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl(CancellableContinuationImpl.kt:508)
at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$default(CancellableContinuationImpl.kt:497)
at kotlinx.coroutines.CancellableContinuationImpl.resumeWith(CancellableContinuationImpl.kt:368)
at androidx.compose.runtime.Recomposer$recompositionRunner$2$unregisterApplyObserver$1.invoke(Recomposer.kt:979)
at androidx.compose.runtime.Recomposer$recompositionRunner$2$unregisterApplyObserver$1.invoke(Recomposer.kt:973)
at androidx.compose.runtime.snapshots.SnapshotKt.advanceGlobalSnapshot(Snapshot.kt:1815)
at androidx.compose.runtime.snapshots.SnapshotKt.advanceGlobalSnapshot(Snapshot.kt:1830)
at androidx.compose.runtime.snapshots.SnapshotKt.access$advanceGlobalSnapshot(Snapshot.kt:1)
at androidx.compose.runtime.snapshots.Snapshot$Companion.sendApplyNotifications(Snapshot.kt:583)
at androidx.compose.ui.test.ApplyingContinuationInterceptor$SendApplyContinuation.resumeWith(ApplyingContinuationInterceptor.kt:66)
at androidx.compose.ui.test.FrameDeferringContinuationInterceptor$FrameDeferredContinuation.resumeWith(FrameDeferringContinuationInterceptor.kt:194)
at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:283)
at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith$default(DispatchedContinuation.kt:278)
at kotlinx.coroutines.internal.ScopeCoroutine.afterCompletion(Scopes.kt:27)
at kotlinx.coroutines.JobSupport.continueCompleting(JobSupport.kt:940)
at kotlinx.coroutines.JobSupport.access$continueCompleting(JobSupport.kt:25)
at kotlinx.coroutines.JobSupport$ChildCompletion.invoke(JobSupport.kt:1159)
at kotlinx.coroutines.JobSupport.notifyCompletion(JobSupport.kt:1497)
at kotlinx.coroutines.JobSupport.completeStateFinalization(JobSupport.kt:325)
at kotlinx.coroutines.JobSupport.finalizeFinishingState(JobSupport.kt:242)
at kotlinx.coroutines.JobSupport.tryMakeCompletingSlowPath(JobSupport.kt:910)
at kotlinx.coroutines.JobSupport.tryMakeCompleting(JobSupport.kt:867)
at kotlinx.coroutines.JobSupport.makeCompletingOnce$kotlinx_coroutines_core(JobSupport.kt:832)
at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:100)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
at androidx.compose.ui.test.ApplyingContinuationInterceptor$SendApplyContinuation.resumeWith(ApplyingContinuationInterceptor.kt:65)
at androidx.compose.ui.test.FrameDeferringContinuationInterceptor$FrameDeferredContinuation.resumeWith(FrameDeferringContinuationInterceptor.kt:194)
at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:179)
at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:168)
at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:474)
at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl(CancellableContinuationImpl.kt:508)
at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$default(CancellableContinuationImpl.kt:497)
at kotlinx.coroutines.CancellableContinuationImpl.resumeWith(CancellableContinuationImpl.kt:368)
at kotlinx.coroutines.ResumeOnCompletion.invoke(JobSupport.kt:1391)
at kotlinx.coroutines.JobSupport.completeStateFinalization(JobSupport.kt:320)
at kotlinx.coroutines.JobSupport.tryFinalizeSimpleState(JobSupport.kt:297)
at kotlinx.coroutines.JobSupport.tryMakeCompleting(JobSupport.kt:860)
at kotlinx.coroutines.JobSupport.makeCompletingOnce$kotlinx_coroutines_core(JobSupport.kt:832)
at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:100)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:115)
at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:103)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684)Zach Klippenstein (he/him) [MOD]
11/22/2023, 8:48 PMvide
11/22/2023, 8:57 PMZach Klippenstein (he/him) [MOD]
11/22/2023, 8:59 PMZach Klippenstein (he/him) [MOD]
11/22/2023, 8:59 PMat <mypackage>(:19) <- helper functions
at <mypackage>(:17) <- helper functions
at <mypackage>.invokeSuspend(:266) <- in a LaunchedEffect
is switching threads?vide
11/22/2023, 9:12 PMLaunchedEffect doesn't do any context switchesshikasd
11/22/2023, 9:12 PMsetContent from the test thread, it is possible that LaunchedEffect also going to execute in the same threadvide
11/22/2023, 9:13 PMmyanmarking
11/22/2023, 9:15 PMvide
11/22/2023, 9:17 PMZach Klippenstein (he/him) [MOD]
11/22/2023, 9:18 PMif you callIt shouldn’t though, and if it did then it would fail much more regularly since that’s the main recommended way to use it.from the test thread, it is possible thatsetContentalso going to execute in the same threadLaunchedEffect
myanmarking
11/22/2023, 9:18 PMvide
11/22/2023, 9:18 PMZach Klippenstein (he/him) [MOD]
11/22/2023, 9:18 PMshikasd
11/22/2023, 9:19 PMApplyingContinuationInterceptor$SendApplyContinuation and TestMonotonicClock is in the trace that is not supposed to be mainZach Klippenstein (he/him) [MOD]
11/22/2023, 9:20 PMvide
11/22/2023, 9:21 PMvide
11/22/2023, 10:30 PMZach Klippenstein (he/him) [MOD]
11/22/2023, 10:31 PMvide
11/22/2023, 10:32 PMvide
11/23/2023, 9:26 AM11-23 11:18:55.592 2224 2327 V CX_LoadingPage: LoadingPage LaunchedEffect running on thread Thread[DefaultDispatcher-worker-20,5,main]Zach Klippenstein (he/him) [MOD]
11/23/2023, 9:18 PMvide
02/20/2025, 1:53 PMLaunchedEffect(...) {
withContext(<http://Dispatchers.IO|Dispatchers.IO>) { Log.d("DEBUG", "Hello, world!") }
Log.d("DEBUG", "Hello, {Thread.currentThread()}!") // on a worker thread
}vide
02/20/2025, 1:54 PMZach Klippenstein (he/him) [MOD]
02/20/2025, 2:01 PMvide
02/20/2025, 2:41 PMshikasd
02/22/2025, 4:36 AMHamid
08/06/2025, 10:00 AM