Skip to content

Commit

Permalink
Lifecycle Effect Once API (#425)
Browse files Browse the repository at this point in the history
  • Loading branch information
DevSrSouza authored May 21, 2024
1 parent 764388a commit ae1f915
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import cafe.adriel.voyager.core.lifecycle.LifecycleEffect
import cafe.adriel.voyager.core.lifecycle.LifecycleEffectOnce
import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.core.screen.uniqueScreenKey
import cafe.adriel.voyager.navigator.LocalNavigator
Expand All @@ -36,6 +37,9 @@ data class BasicNavigationScreen(
onStarted = { Log.d("Navigator", "Start screen #$index") },
onDisposed = { Log.d("Navigator", "Dispose screen #$index") }
)
LifecycleEffectOnce {
Log.d("Navigator", "On screen first appear #$index")
}

val navigator = LocalNavigator.currentOrThrow

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package cafe.adriel.voyager.core.lifecycle

import cafe.adriel.voyager.core.concurrent.ThreadSafeMap
import cafe.adriel.voyager.core.concurrent.ThreadSafeSet
import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.core.screen.ScreenKey

internal object LifecycleEffectStore : ScreenDisposable {
private val executedLifecycles = ThreadSafeMap<ScreenKey, ThreadSafeSet<String>>()

fun store(screen: Screen, effectKey: String) {
val set = executedLifecycles.getOrPut(screen.key) { ThreadSafeSet() }
set.add(effectKey)
}

fun hasExecuted(screen: Screen, effectKey: String): Boolean =
executedLifecycles.get(screen.key)?.contains(effectKey) == true

override fun onDispose(screen: Screen) {
executedLifecycles.remove(screen.key)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,16 @@ package cafe.adriel.voyager.core.lifecycle

import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import cafe.adriel.voyager.core.annotation.ExperimentalVoyagerApi
import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.core.screen.randomUuid

@Deprecated(
message = "This API is a wrap on top on DisposableEffect, will be removed in 1.1.0, replace with DisposableEffect"
)
@Composable
public fun Screen.LifecycleEffect(
onStarted: () -> Unit = {},
Expand All @@ -16,6 +23,23 @@ public fun Screen.LifecycleEffect(
}
}

@ExperimentalVoyagerApi
@Composable
public fun Screen.LifecycleEffectOnce(onFirstAppear: () -> Unit) {
val uniqueCompositionKey = rememberSaveable { randomUuid() }

val lifecycleEffectStore = remember {
ScreenLifecycleStore.get(this) { LifecycleEffectStore }
}

LaunchedEffect(Unit) {
if (lifecycleEffectStore.hasExecuted(this@LifecycleEffectOnce, uniqueCompositionKey).not()) {
lifecycleEffectStore.store(this@LifecycleEffectOnce, uniqueCompositionKey)
onFirstAppear()
}
}
}

@Composable
public fun rememberScreenLifecycleOwner(
screen: Screen
Expand Down

0 comments on commit ae1f915

Please sign in to comment.