Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
hoc081098 committed Jan 6, 2024
1 parent deba12a commit 2840a91
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 55 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.hoc081098.solivagant.navigation.internal

import com.hoc081098.kmp.viewmodel.SavedStateHandle
import com.hoc081098.kmp.viewmodel.SavedStateHandleFactory
import com.hoc081098.solivagant.navigation.BaseRoute
import com.hoc081098.solivagant.navigation.Navigator
import com.hoc081098.solivagant.navigation.Serializable
Expand All @@ -10,6 +11,7 @@ import kotlin.reflect.KClass
public interface NavigationExecutor : Navigator {
public fun <T : BaseRoute> routeFor(destinationId: DestinationId<T>): T
public fun <T : BaseRoute> savedStateHandleFor(destinationId: DestinationId<T>): SavedStateHandle
public fun <T : BaseRoute> savedStateHandleFactoryFor(destinationId: DestinationId<T>): SavedStateHandleFactory
public fun <T : BaseRoute> storeFor(destinationId: DestinationId<T>): Store
public fun <T : BaseRoute> extra(destinationId: DestinationId<T>): Serializable

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,22 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.SaveableStateHolder
import androidx.compose.runtime.saveable.rememberSaveableStateHolder
import androidx.compose.runtime.snapshotFlow
import androidx.compose.runtime.snapshots.Snapshot
import androidx.compose.ui.Modifier
import com.hoc081098.kmp.viewmodel.Closeable
import com.hoc081098.kmp.viewmodel.compose.SavedStateHandleFactoryProvider
import com.hoc081098.kmp.viewmodel.compose.ViewModelStoreOwnerProvider
import com.hoc081098.solivagant.navigation.internal.MultiStackNavigationExecutor
import com.hoc081098.solivagant.navigation.internal.OnBackPressedCallback
import com.hoc081098.solivagant.navigation.internal.StackEntry
import com.hoc081098.solivagant.navigation.internal.ViewModelStoreOwnerCloseable
import com.hoc081098.solivagant.navigation.internal.StackEntryViewModelStoreOwner
import com.hoc081098.solivagant.navigation.internal.WeakReference
import com.hoc081098.solivagant.navigation.internal.currentBackPressedDispatcher
import com.hoc081098.solivagant.navigation.internal.rememberNavigationExecutor
Expand Down Expand Up @@ -74,23 +78,28 @@ private fun <T : BaseRoute> Show(
// it is available when the destination is cleared. Which, because of animations,
// only happens after this leaves composition. Which means we can't rely on
// DisposableEffect to clean up this reference (as it'll be cleaned up too early)
remember(entry, executor, saveableStateHolder) {
executor.storeFor(entry.id).getOrCreate(SaveableCloseable::class) {
SaveableCloseable(entry.id.value, WeakReference(saveableStateHolder))
}
val saveableCloseable = remember(entry, executor, saveableStateHolder) {
executor
.storeFor(entry.id)
.getOrCreate(SaveableCloseable::class) {
SaveableCloseable(
entry.id.value,
WeakReference(saveableStateHolder),
)
}
}

val viewModelStoreOwner = saveableCloseable
.viewModelStoreOwnerState
.value // <-- This will cause the recomposition when the value is cleared.
?: return

saveableStateHolder.SaveableStateProvider(entry.id.value) {
ViewModelStoreOwnerProvider(
viewModelStoreOwner = executor
.storeFor(entry.id)
.getOrCreate(
ViewModelStoreOwnerCloseable::class,
::ViewModelStoreOwnerCloseable,
),
viewModelStoreOwner = viewModelStoreOwner,
) {
SavedStateHandleFactoryProvider(
savedStateHandleFactory = { executor.savedStateHandleFor(entry.destinationId) },
savedStateHandleFactory = executor.savedStateHandleFactoryFor(entry.destinationId),
) {
entry.destination.content(entry.route)
}
Expand All @@ -102,7 +111,17 @@ internal class SaveableCloseable(
private val id: String,
private val saveableStateHolderRef: WeakReference<SaveableStateHolder>,
) : Closeable {
private val _viewModelStoreOwnerState: MutableState<StackEntryViewModelStoreOwner?> =
mutableStateOf(StackEntryViewModelStoreOwner())

inline val viewModelStoreOwnerState: State<StackEntryViewModelStoreOwner?> get() = _viewModelStoreOwnerState

override fun close() {
Snapshot.withMutableSnapshot {
_viewModelStoreOwnerState.value?.clearIfInitialized()
_viewModelStoreOwnerState.value = null
}

saveableStateHolderRef.get()?.removeState(id)
saveableStateHolderRef.clear()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.hoc081098.solivagant.navigation.internal

import androidx.compose.runtime.State
import com.hoc081098.kmp.viewmodel.SavedStateHandle
import com.hoc081098.kmp.viewmodel.SavedStateHandleFactory
import com.hoc081098.solivagant.navigation.BaseRoute
import com.hoc081098.solivagant.navigation.NavRoot
import com.hoc081098.solivagant.navigation.NavRoute
Expand Down Expand Up @@ -67,6 +68,11 @@ internal class MultiStackNavigationExecutor(
return viewModel.provideSavedStateHandle(entry.id, entry.route)
}

override fun <T : BaseRoute> savedStateHandleFactoryFor(destinationId: DestinationId<T>): SavedStateHandleFactory {
val entry = entryFor(destinationId)
return viewModel.provideSavedStateHandleFactory(entry.id, entry.route)
}

override fun <T : BaseRoute> storeFor(destinationId: DestinationId<T>): NavigationExecutor.Store {
val entry = entryFor(destinationId)
return storeFor(entry.id)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
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.navigation.BaseRoute
import com.hoc081098.solivagant.navigation.EXTRA_ROUTE
Expand All @@ -12,25 +13,33 @@ internal class StoreViewModel(
) : ViewModel() {
private val stores = mutableMapOf<StackEntry.Id, NavigationExecutorStore>()
private val savedStateHandles = mutableMapOf<StackEntry.Id, SavedStateHandle>()
private val savedStateHandleFactories = mutableMapOf<StackEntry.Id, SavedStateHandleFactory>()

internal val savedNavRoot: NavRoot? get() = globalSavedStateHandle[SAVED_START_ROOT_KEY]

fun provideStore(id: StackEntry.Id): NavigationExecutor.Store {
internal fun provideStore(id: StackEntry.Id): NavigationExecutor.Store {
return stores.getOrPut(id) { NavigationExecutorStore() }
}

fun provideSavedStateHandle(id: StackEntry.Id, route: BaseRoute): SavedStateHandle {
internal fun provideSavedStateHandle(id: StackEntry.Id, route: BaseRoute): SavedStateHandle {
return savedStateHandles.getOrPut(id) {
createSavedStateHandleAndSetSavedStateProvider(id.value, globalSavedStateHandle)
.apply { this[EXTRA_ROUTE] = route }
}
}

fun removeEntry(id: StackEntry.Id) {
internal fun provideSavedStateHandleFactory(id: StackEntry.Id, route: BaseRoute): SavedStateHandleFactory {
return savedStateHandleFactories.getOrPut(id) {
SavedStateHandleFactory { provideSavedStateHandle(id, route) }
}
}

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

savedStateHandles.remove(id)
savedStateHandleFactories.remove(id)
globalSavedStateHandle.removeSavedStateProvider(id.value)
globalSavedStateHandle.remove<Any>(id.value)
}
Expand All @@ -47,6 +56,7 @@ internal class StoreViewModel(
globalSavedStateHandle.remove<Any>(key.value)
}
savedStateHandles.clear()
savedStateHandleFactories.clear()
}

internal fun setInputStartRoot(root: NavRoot) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package com.hoc081098.solivagant.navigation.internal

import com.hoc081098.kmp.viewmodel.Closeable
import com.hoc081098.kmp.viewmodel.ViewModelStore
import com.hoc081098.kmp.viewmodel.ViewModelStoreOwner
import kotlin.LazyThreadSafetyMode.NONE

internal expect fun createViewModelStore(): ViewModelStore

internal class ViewModelStoreOwnerCloseable : Closeable, ViewModelStoreOwner {
private val viewModelStoreLazy = lazy { createViewModelStore() }
internal class StackEntryViewModelStoreOwner : ViewModelStoreOwner {
private val viewModelStoreLazy = lazy(NONE) { createViewModelStore() }

override fun close() {
fun clearIfInitialized() {
if (viewModelStoreLazy.isInitialized()) {
viewModelStoreLazy.value.clear()
}
Expand Down
36 changes: 0 additions & 36 deletions sample/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -43,41 +43,5 @@ android {

dependencies {
implementation(project(":sample:shared"))
// implementation(platform(libs.androidx.compose.bom))
//
// implementation(libs.androidx.lifecycle.runtime.compose)
//
// implementation(libs.androidx.compose.ui.ui)
// debugImplementation(libs.androidx.compose.ui.tooling)
// implementation(libs.androidx.compose.ui.tooling.preview)
// implementation(libs.androidx.compose.foundation)
// implementation(libs.androidx.compose.material3)
// implementation(libs.androidx.compose.material)
// implementation(libs.androidx.compose.runtime)
implementation(libs.androidx.activity.compose)
// implementation(libs.androidx.navigation.compose)

// implementation(libs.koin.androidx.compose)
// implementation(libs.coil.compose)

// implementation(libs.kotlinx.collections.immutable)
}

// tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
// kotlinOptions {
// val buildDirAbsolutePath = project.layout.buildDirectory.map { it.asFile.absolutePath }.get()
//
// if (project.findProperty("composeCompilerReports") == "true") {
// freeCompilerArgs = freeCompilerArgs + listOf(
// "-P",
// "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=$buildDirAbsolutePath/compose_compiler",
// )
// }
// if (project.findProperty("composeCompilerMetrics") == "true") {
// freeCompilerArgs = freeCompilerArgs + listOf(
// "-P",
// "plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=$buildDirAbsolutePath/compose_compiler",
// )
// }
// }
// }

0 comments on commit 2840a91

Please sign in to comment.