Skip to content

Commit

Permalink
create MultiStackNavigationExecutor in ViewModel
Browse files Browse the repository at this point in the history
  • Loading branch information
hoc081098 committed Feb 1, 2024
1 parent 6373780 commit 05469a6
Show file tree
Hide file tree
Showing 9 changed files with 59 additions and 81 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import android.os.Bundle
import android.os.Parcelable
import androidx.lifecycle.SavedStateHandle

internal actual fun SavedStateHandle.setSavedStateProvider(
internal actual fun SavedStateHandle.setSavedStateProviderX(
key: String,
savedStateFactory: () -> Map<String, Any?>,
) = setSavedStateProvider(key) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,7 @@ internal class MultiStackNavigationExecutor(
val canNavigateBack: State<Boolean>
get() = stack.canNavigateBack

internal fun saveState() {
viewModel.globalSavedStateHandle[SAVED_STATE_STACK] = stack.saveState()
}

init {
viewModel
.globalSavedStateHandle
.setSavedStateProvider(SAVED_STATE_STACK, stack::saveState)

_lifecycleOwner
.flatMapLatest { it?.lifecycle?.eventFlow ?: emptyFlow() }
.onEach(stack::handleLifecycleEvent)
Expand Down Expand Up @@ -121,10 +113,7 @@ internal class MultiStackNavigationExecutor(
_lifecycleOwner.value = lifecycleOwner
}

internal companion object {
const val SAVED_STATE_STACK = "com.hoc081098.solivagant.navigation.stack"
}

//region RememberObserver
override fun onAbandoned() {
_lifecycleOwner.value = null
scope.cancel()
Expand All @@ -136,4 +125,5 @@ internal class MultiStackNavigationExecutor(
}

override fun onRemembered() = Unit
//endregion
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,44 +23,17 @@ internal fun rememberNavigationExecutor(
},
),
): MultiStackNavigationExecutor {
val lifecycleOwner = LocalLifecycleOwner.current

// setInputStartRoot must be called before getMultiStackNavigationExecutor
viewModel.setInputStartRoot(startRoot)

val lifecycleOwner = LocalLifecycleOwner.current
val executor = remember(viewModel) {
val contentDestinations = destinations.filterIsInstance<ContentDestination<*>>()

val navState = viewModel.getSavedStackState()
val hostLifecycleState = lifecycleOwner.lifecycle.currentState

val stack = if (navState == null) {
MultiStack.createWith(
root = viewModel.savedNavRoot!!,
destinations = contentDestinations,
hostLifecycleState = hostLifecycleState,
onStackEntryRemoved = viewModel::removeEntry,
)
} else {
MultiStack.fromState(
root = viewModel.savedNavRoot!!,
bundle = navState,
destinations = contentDestinations,
hostLifecycleState = hostLifecycleState,
onStackEntryRemoved = viewModel::removeEntry,
)
}

@Suppress("ViewModelForwarding")
MultiStackNavigationExecutor(
stack = stack,
viewModel = viewModel,
onRootChanged = viewModel::setStartRoot,
viewModel.createMultiStackNavigationExecutor(
contentDestinations = destinations.filterIsInstance<ContentDestination<*>>(),
hostLifecycleState = lifecycleOwner.lifecycle.currentState,
)
}

executor.setLifecycleOwner(lifecycleOwner)

NonAndroidSaveStackState(executor)

return executor
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ package com.hoc081098.solivagant.navigation.internal
import com.hoc081098.kmp.viewmodel.SavedStateHandle
import com.hoc081098.kmp.viewmodel.SavedStateHandleFactory
import com.hoc081098.kmp.viewmodel.ViewModel
import com.hoc081098.solivagant.lifecycle.Lifecycle
import com.hoc081098.solivagant.navigation.BaseRoute
import com.hoc081098.solivagant.navigation.ContentDestination
import com.hoc081098.solivagant.navigation.EXTRA_ROUTE
import com.hoc081098.solivagant.navigation.NavRoot
import com.hoc081098.solivagant.navigation.internal.MultiStackNavigationExecutor.Companion.SAVED_STATE_STACK

internal class StoreViewModel(
internal val globalSavedStateHandle: SavedStateHandle,
Expand All @@ -15,7 +16,14 @@ internal class StoreViewModel(
private val savedStateHandles = mutableMapOf<StackEntry.Id, SavedStateHandle>()
private val savedStateHandleFactories = mutableMapOf<StackEntry.Id, SavedStateHandleFactory>()

internal val savedNavRoot: NavRoot? get() = globalSavedStateHandle[SAVED_START_ROOT_KEY]
private var stack: MultiStack? = null
private var executor: MultiStackNavigationExecutor? = null

init {
globalSavedStateHandle.setSavedStateProviderX(SAVED_STATE_STACK) {
checkNotNull(stack) { "Stack is null. This should never happen" }.saveState()
}
}

internal fun provideStore(id: StackEntry.Id): NavigationExecutor.Store {
return stores.getOrPut(id) { NavigationExecutorStore() }
Expand All @@ -34,7 +42,7 @@ internal class StoreViewModel(
}
}

internal fun removeEntry(id: StackEntry.Id) {
private fun removeEntry(id: StackEntry.Id) {
val store = stores.remove(id)
store?.close()

Expand Down Expand Up @@ -82,14 +90,49 @@ internal class StoreViewModel(
}
}

internal fun setStartRoot(root: NavRoot) {
private fun setStartRoot(root: NavRoot) {
globalSavedStateHandle[SAVED_START_ROOT_KEY] = root
}

internal fun getSavedStackState(): Map<String, Any?>? =
globalSavedStateHandle.getAsMap(SAVED_STATE_STACK)
fun createMultiStackNavigationExecutor(
contentDestinations: List<ContentDestination<*>>,
hostLifecycleState: Lifecycle.State,
): MultiStackNavigationExecutor =
executor
?: MultiStackNavigationExecutor(
stack = createMultiStackIfNeeded(contentDestinations, hostLifecycleState),
viewModel = this,
onRootChanged = ::setStartRoot,
).also { this.executor = it }

private fun createMultiStackIfNeeded(
contentDestinations: List<ContentDestination<*>>,
hostLifecycleState: Lifecycle.State,
): MultiStack {
this.stack?.let { return it }

val navState = globalSavedStateHandle.getAsMap(SAVED_STATE_STACK)
val savedNavRoot: NavRoot? = globalSavedStateHandle[SAVED_START_ROOT_KEY]
return if (navState == null) {
MultiStack.createWith(
root = savedNavRoot!!,
destinations = contentDestinations,
hostLifecycleState = hostLifecycleState,
onStackEntryRemoved = ::removeEntry,
)
} else {
MultiStack.fromState(
root = savedNavRoot!!,
bundle = navState,
destinations = contentDestinations,
hostLifecycleState = hostLifecycleState,
onStackEntryRemoved = ::removeEntry,
)
}.also { this.stack = it }
}

private companion object {
private const val SAVED_STATE_STACK = "com.hoc081098.solivagant.navigation.stack"
private const val SAVED_START_ROOT_KEY = "com.hoc081098.solivagant.navigation.store.start_root"
private const val SAVED_INPUT_START_ROOT_KEY = "com.hoc081098.solivagant.navigation.store.input_start_root"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package com.hoc081098.solivagant.navigation.internal

import com.hoc081098.kmp.viewmodel.SavedStateHandle

internal expect fun SavedStateHandle.setSavedStateProvider(
internal expect fun SavedStateHandle.setSavedStateProviderX(
key: String,
savedStateFactory: () -> Map<String, Any?>,
)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package com.hoc081098.solivagant.navigation.internal

import com.hoc081098.kmp.viewmodel.SavedStateHandle

internal actual fun SavedStateHandle.setSavedStateProvider(
internal actual fun SavedStateHandle.setSavedStateProviderX(
key: String,
savedStateFactory: () -> Map<String, Any?>,
) {
Expand Down

0 comments on commit 05469a6

Please sign in to comment.