From b9f180a9b593bbd03efc6e724f0b94452e9514bc Mon Sep 17 00:00:00 2001 From: Yongshun Shreck Ye Date: Sun, 5 Jan 2025 00:20:28 +0800 Subject: [PATCH] Add `previousBackStackEntryFlow` in `NavController` and `NavController.previousBackStackEntryAsState` with their KDocs copied and adapted from related functions, and extract a common `List.getPreviousBackStackEntry` function --- .../navigation/compose/NavHostController.kt | 16 ++++++++++ .../java/androidx/navigation/NavController.kt | 29 ++++++++++++++----- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/navigation/navigation-compose/src/main/java/androidx/navigation/compose/NavHostController.kt b/navigation/navigation-compose/src/main/java/androidx/navigation/compose/NavHostController.kt index 0eb9377074e79..fc77cbf47ddfc 100644 --- a/navigation/navigation-compose/src/main/java/androidx/navigation/compose/NavHostController.kt +++ b/navigation/navigation-compose/src/main/java/androidx/navigation/compose/NavHostController.kt @@ -27,6 +27,7 @@ import androidx.compose.ui.platform.LocalContext import androidx.navigation.NavBackStackEntry import androidx.navigation.NavController import androidx.navigation.NavDestination +import androidx.navigation.NavGraph import androidx.navigation.NavHostController import androidx.navigation.Navigator @@ -42,6 +43,21 @@ public fun NavController.currentBackStackEntryAsState(): State = + previousBackStackEntryFlow.collectAsState(null) + /** * Creates a NavHostController that handles the adding of the [ComposeNavigator] and * [DialogNavigator]. Additional [Navigator] instances can be passed through [navigators] to be diff --git a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt b/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt index 1174a14806bf6..4d8595e1a4373 100644 --- a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt +++ b/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt @@ -59,6 +59,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.map import kotlinx.serialization.InternalSerializationApi import kotlinx.serialization.serializer @@ -2954,6 +2955,15 @@ public open class NavController( public val currentBackStackEntryFlow: Flow = _currentBackStackEntryFlow.asSharedFlow() + private fun List.getPreviousBackStackEntry(): NavBackStackEntry? { + val iterator = reversed().iterator() + // throw the topmost destination away. + if (iterator.hasNext()) { + iterator.next() + } + return iterator.asSequence().firstOrNull { entry -> entry.destination !is NavGraph } + } + /** * The previous visible [NavBackStackEntry]. * @@ -2963,14 +2973,17 @@ public open class NavController( * two visible entries */ public open val previousBackStackEntry: NavBackStackEntry? - get() { - val iterator = backQueue.reversed().iterator() - // throw the topmost destination away. - if (iterator.hasNext()) { - iterator.next() - } - return iterator.asSequence().firstOrNull { entry -> entry.destination !is NavGraph } - } + get() = backQueue.getPreviousBackStackEntry() + + /** + * A [Flow] that will emit the previous visible [NavBackStackEntry] whenever it changes. + * + * This skips over any [NavBackStackEntry] that is associated with a [NavGraph]. + * + * If the back stack has less than two visible entries, no item will be emitted. + */ + public val previousBackStackEntryFlow: Flow = + currentBackStack.map { it.getPreviousBackStackEntry() } public companion object { private const val TAG = "NavController"