Hi! I have the following set up with `DisposableEf...
# compose
s
Hi! I have the following set up with
DisposableEffect
and navigation compose, and expect the behaviour as described but got something different. Any pointers to what might be the issue or could it be that my understanding of how disposable effects is meant to work is wrong?
Copy code
@Composable
fun ReusableDisposableEffect() {
  DisposableEffect(Unit) {
    println("Effect")
    
    onDispose {
      println("Disposed")
    }
  }
}

fun ScreenA() {
  ReusableDisposableEffect()
}

fun ScreenB() {
  ReusableDisposableEffect()
}

// action: navigate from ScreenA to ScreenB with navigation compose

// Expected prints:
- Effect
- Disposed
- Effect

// Actual prints:
- Effect
- Effect
- Disposed
i
When you navigate to a new screen with a transition (like the default crossfade), during that transition both the old screen and the new screen are going to be part of composition. It is only after the transition completes that the old screen leaves composition. Hence, you get screen A entering composition (when you're on screen A), screen B entering composition (when the transition starts), and only then screen A leaving composition (when the transition finishes)
s
Thanks, @Ian Lake. I thought this was the problem as well and tried disabling the transition animation to fix it. The default way of disabling the transition (code snippet A) doesn’t work (not sure why), and I tried disabling the transition this other way (code snippet B) and that worked, but the
DisposableEffect
still didn’t have the expected behaviour as described above.
Copy code
// Code snippet A: couldn't disable transition animation with this and as such could not verify transition as the cause of the issue
NavHost(
  enterTransition = { EnterTransition.None },
  exitTransition = { ExitTransition.None } 
)

// Code snippet B: disabled transition animation this way, but DisposableEffect issue remains
NavHost(
  enterTransition = { 
    fadeIn(
      initialAlpha = 1F,
      animationSpec = tween(durationMillis = 0, delayMillis = 0),
     )
  },
  exitTransition = { fadeOut(animationSpec = tween(durationMillis = 0, delayMillis = 0)) } 
)
upgraded my compose version (from latest stable: 2023.10.01) to latest beta (1.6.0-beta03) and
EnterTransition.None
and
ExitTransition.None
now works, but the original issue persists.
i
If you want something that is transition aware, DisposableEffect just isn't the right tool for this. Instead, use LifecycleResumeEffect: https://developer.android.com/reference/kotlin/androidx/lifecycle/compose/package-summary#LifecycleResumeEffect(kotlin.Any,androidx.lifecycle.LifecycleOwner,kotlin.Function1) This takes advantage of the fact that a destination is only RESUMED when it has settled - i.e., no transition is running. That means that you'd get screen A enter (when you are on that screen), screen A disposed (when the transition to screen B starts), screen A enter (when the transition to screen B finishes)
😱 1
🎆 1
You'll need to upgrade to
lifecycle-runtime-compose
2.7 to get that API, currently in rc02 (going stable in January)
s
Thanks a lot, Ian. I’ll check this out.