Skip to content

Commit

Permalink
Adding onDispose callback api to Experimental LifecycleEffectOnce
Browse files Browse the repository at this point in the history
  • Loading branch information
DevSrSouza committed Oct 7, 2024
1 parent 02dd74e commit bb2f79c
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ data class BasicNavigationScreen(
)
LifecycleEffectOnce {
Log.d("Navigator", "On screen first appear #$index")
onDispose {
Log.d("Navigator", "On screen dispose")
}
}

val navigator = LocalNavigator.currentOrThrow
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,23 @@ 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>>()
private val executedLifecycles = ThreadSafeMap<ScreenKey, ThreadSafeSet<LifecycleEffectOnceScope>>()

fun store(screen: Screen, effectKey: String) {
fun store(screen: Screen, effectKey: String): LifecycleEffectOnceScope {
val set = executedLifecycles.getOrPut(screen.key) { ThreadSafeSet() }
set.add(effectKey)
val scope = LifecycleEffectOnceScope(uniqueKey = effectKey, set.size + 1)
set.add(scope)

return scope
}

fun hasExecuted(screen: Screen, effectKey: String): Boolean =
executedLifecycles.get(screen.key)?.contains(effectKey) == true
executedLifecycles.get(screen.key)?.any { it.uniqueKey == effectKey } == true

override fun onDispose(screen: Screen) {
executedLifecycles.remove(screen.key)
val scopes = executedLifecycles.remove(screen.key)
scopes?.sortedBy { it.registerOrderIndex }?.reversed()?.forEach { scope ->
scope.onDisposed?.invoke()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,22 @@ public fun Screen.LifecycleEffect(
}
}

@ExperimentalVoyagerApi
public data class LifecycleEffectOnceScope(
val uniqueKey: String,
val registerOrderIndex: Int,
) {
internal var onDisposed: (() -> Unit)? = null

@ExperimentalVoyagerApi
public fun onDispose(onDisposed: () -> Unit) {
this.onDisposed = onDisposed
}
}

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

val lifecycleEffectStore = remember {
Expand All @@ -34,8 +47,8 @@ public fun Screen.LifecycleEffectOnce(onFirstAppear: () -> Unit) {

LaunchedEffect(Unit) {
if (lifecycleEffectStore.hasExecuted(this@LifecycleEffectOnce, uniqueCompositionKey).not()) {
lifecycleEffectStore.store(this@LifecycleEffectOnce, uniqueCompositionKey)
onFirstAppear()
val scope = lifecycleEffectStore.store(this@LifecycleEffectOnce, uniqueCompositionKey)
onFirstAppear(scope)
}
}
}
Expand Down

0 comments on commit bb2f79c

Please sign in to comment.