diff --git a/modo-compose/src/main/java/com/github/terrakok/modo/ContainerScreen.kt b/modo-compose/src/main/java/com/github/terrakok/modo/ContainerScreen.kt index 3362e91b..9f9ceb9c 100644 --- a/modo-compose/src/main/java/com/github/terrakok/modo/ContainerScreen.kt +++ b/modo-compose/src/main/java/com/github/terrakok/modo/ContainerScreen.kt @@ -60,7 +60,7 @@ abstract class ContainerScreen>( // TODO: print logs when fallback to state ?: state + override fun toString(): String = "NavModel(navigationState=$navigationState, screenKey=$screenKey)" + companion object CREATOR : Parcelable.Creator> { override fun createFromParcel(parcel: Parcel): NavModel { val state = parcel.readParcelable(NavModel::class.java.classLoader)!! diff --git a/modo-compose/src/main/java/com/github/terrakok/modo/Modo.kt b/modo-compose/src/main/java/com/github/terrakok/modo/Modo.kt index 4271fe13..a99b3a14 100644 --- a/modo-compose/src/main/java/com/github/terrakok/modo/Modo.kt +++ b/modo-compose/src/main/java/com/github/terrakok/modo/Modo.kt @@ -2,6 +2,7 @@ package com.github.terrakok.modo import android.app.Activity import android.os.Bundle +import android.util.Log import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.getValue @@ -15,12 +16,18 @@ import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleEventObserver import com.github.terrakok.modo.model.ScreenModelStore import com.github.terrakok.modo.util.getActivity +import java.util.concurrent.ConcurrentHashMap object Modo { private const val MODO_SCREEN_COUNTER_KEY = "MODO_SCREEN_COUNTER_KEY" private const val MODO_GRAPH = "MODO_GRAPH" + /** + * Contains root screens to priovide stability of returned instance when use [rememberRootScreen] and return a same instance in per a process. + */ + private val rootScreens: MutableMap> = ConcurrentHashMap() + /** * Saves provided screen with nested graph to bundle for further restoration. */ @@ -48,12 +55,17 @@ object Modo { * Must be called to clear all data from [ScreenModelStore], related with removed screens. */ fun onRootScreenFinished(rootScreen: RootScreen?) { - // TODO: store root screen in memory and clear it here - rootScreen?.let(::clearScreenModel) + if (rootScreen != null) { + Log.d("Modo", "rootScreen removing $rootScreen") + rootScreens.remove(rootScreen.screenKey) + clearScreenModel(rootScreen) + } } /** * Creates [RootScreen] with provided screen, if there is no saved value. Otherwise [RootScreen] is restored from savedState. + * Returns same instance of [RootScreen] for same process. A new instance returned only after process death. + * So you can safelly inject returned value to your DI. * It automatically clears all data from [ScreenModelStore], . * It also saves and restores screenCounterKey for correct [generateScreenKey] usage. * Integration point for your screen hierarchy. You can use this fun to integrate Modo to your Fragment or Activity. @@ -94,8 +106,18 @@ object Modo { ) { screenCounterKey.get() } - // FIXME: return same instance if there was no process death - val rootScreen = rememberSaveable(key = MODO_GRAPH) { + val rootScreen = rememberSaveable( + key = MODO_GRAPH, + saver = Saver( + save = { rootScreen -> + rootScreens.put(rootScreen.screenKey, rootScreen) + rootScreen + }, + restore = { rootScreen -> + rootScreens.get(rootScreen.screenKey)?.let { it as RootScreen } ?: rootScreen + } + ) + ) { RootScreen(rootScreenFactory()) } return rootScreen @@ -103,6 +125,8 @@ object Modo { /** * Creates [RootScreen] with provided screen, if there is no saved value. Otherwise [RootScreen] is restored from savedState. + * Returns same instance of [RootScreen] for same process. A new instance returned only after process death. + * So you can safelly inject returned value to your DI. * It automatically clears all data from [ScreenModelStore], . * It also saves and restores screenCounterKey for correct [generateScreenKey] usage. * Integration point for your screen hierarchy. You can use this fun to integrate Modo to your Fragment or Activity. diff --git a/modo-compose/src/main/java/com/github/terrakok/modo/RootScreen.kt b/modo-compose/src/main/java/com/github/terrakok/modo/RootScreen.kt index 30961323..0d38a7b2 100644 --- a/modo-compose/src/main/java/com/github/terrakok/modo/RootScreen.kt +++ b/modo-compose/src/main/java/com/github/terrakok/modo/RootScreen.kt @@ -8,7 +8,7 @@ import androidx.compose.ui.Modifier import kotlinx.parcelize.Parcelize @Parcelize -class RootScreenState( +data class RootScreenState( internal val screen: T ) : NavigationState { override fun getChildScreens(): List = listOf(screen)