Status Update
Comments
il...@google.com <il...@google.com> #2
This is un-callable in scenarios where the route class is unknown at compile time
Can you include a sample project / code that shows these scenarios in a concrete case?
ph...@bankshift.com <ph...@bankshift.com> #3
For instance, a top-level composable that routes nav commands emitted by an injectable Navigator
class. Or any other implementation where the route class is unknown at compile time, rendering a reified method unusable.
AppContainer {
val navigator = // injected navigator class
val navController = rememberNavController()
LaunchedEffect(Unit) {
navigator.navCommands
.onEach { navCommand ->
when (navCommand) {
is NavCommand.PopBackStack ->
// There is currently no way to pass route class here, forcing it to be first converted to an ID (the functionality for which is annotated library-internal)
navController.popBackStack(
destinationId = navCommand.destinationId,
inclusive = navCommand.inclusive,
saveState = navCommand.saveState,
)
...
}
}
.launchIn(this)
}
NavHost(navController = navController, ...) { ... }
}
ph...@bankshift.com <ph...@bankshift.com> #4
Is there an update for this request? It is similar in nature to
ph...@bankshift.com <ph...@bankshift.com> #5
Another request for non-reified nav:
es...@gmail.com <es...@gmail.com> #6
We already have 3 common and simple requests. I wonder why the haven't responded yet
es...@gmail.com <es...@gmail.com> #7
From
on 10/21/2024: issue 366291612
I tried applying this in a trial project and found that there is a lot of room for improvement. I tried improving it as much as I could based on a project I'm working on. It should scale as much as it could and be reusable in other projects.
I have attached the project in this comment. The package structure might be confusing as it is not separated by modules.
You can see there 2 MainScreen
. MainScreen
is implemented with my Navigation Structure (Not working due to no non-reified api). MainScreenB
is implemented with manually hard-coded navigation and partially using MainNavigation
for BottomNavigation
.
There is also Screen3RootA
and Screen3RootB
which is implemented in the same fashion but Screen3RootB
is implemented manually using DestinationComposable
.
You might notice there are reified functions inside the companion object
of the classes which is supposedly in the class directly but I tried hacking my way through the reified navigation apis
for demonstration purposes.
There is one weird bug when navigating to Screen2
from Screen3
then tapping Screen2
in the BottomNavigation
but it could be mitigated by returning from the function call if the tab is currently selected.
es...@gmail.com <es...@gmail.com> #8
You might want to check this out. Pardon not adding comments.
g....@gmail.com <g....@gmail.com> #9
Somewhat related to this, there is the NavOptionsBuilder.popUpTo()
function which does have a non-reified version of it, but it is annotated with @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
, so it's not part of the supported public API.
g....@gmail.com <g....@gmail.com> #10
I've just realized I can use the reified version for this. I needed the non-reified version for a wrapper I made and did not notice that it does not apply for this minimal sample.
Old comment:
I sometimes create navigation graphs with arguments. With those, popping the entire graph from a sub destination is a bit awkward. I can't always pop up to the start destination, because maybe that's been popped already (e.g. navigate with navOptions
). Besides, I find referencing the graph itself a lot more convenient and clearer.
Here a minimal example:
@Serializable
data object MainGraph
@Serializable
data object MainGraphStartDestination
@Serializable
data class SubGraphWithArgs(val something: String)
@Serializable
data object SubGraphWithArgsStartDestination
@Composable
private fun Example(navController: NavHostController) {
NavHost(
navController = navController,
startDestination = MainGraph,
modifier = Modifier.fillMaxSize(),
) {
navigation<MainGraph>(MainGraphStartDestination) {
composable<MainGraphStartDestination> {
Box(
Modifier
.background(Color.Red)
.fillMaxSize()
.clickable {
navController.navigate(SubGraphWithArgs("Some input"))
}
)
}
navigation<SubGraphWithArgs>(SubGraphWithArgsStartDestination) {
composable<SubGraphWithArgsStartDestination> { navBackStackEntry ->
val subGraphWithArgs = remember(navBackStackEntry) {
navController
.getBackStackEntry(navBackStackEntry.destination.parent!!.id)
.toRoute<SubGraphWithArgs>()
}
Box(
Modifier
.background(Color.Green)
.clickable {
// I should be able to just use SubGraphWithArgs::class. This screen
// may not care about `SubGraphWithArgs`, but it needs it to be able
// to pop the graph.
navController.popBackStack(
subGraphWithArgs,
inclusive = false,
)
// This also works, but I shouldn't use generateHashCode()
//navController.popBackStack(
// SubGraphWithArgs::class.serializer().generateHashCode(),
// inclusive = false,
//)
}
.fillMaxSize(),
)
}
}
}
}
}
jb...@google.com <jb...@google.com>
ap...@google.com <ap...@google.com> #11
Project: platform/frameworks/support
Branch: androidx-main
Author: Clara Fok <
Link:
Add popBackStack non-reified overload for route from KClass
Expand for full commit details
Add popBackStack non-reified overload for route from KClass
Test: ./gradlew navigation:navigation-runtime:cC
Bug: 363225480
Relnote: "Added non-reified overload for popBackStack with KClass<*>"
Change-Id: I6f7884836f74d263d9d342df1593c61a9b9835ba
Files:
- M
navigation/navigation-runtime/api/current.txt
- M
navigation/navigation-runtime/api/restricted_current.txt
- M
navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerRouteTest.kt
- M
navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
Hash: bfdb50da82e5ffdd7a0a096681e84607e6d46bc1
Date: Mon Dec 02 16:05:36 2024
cl...@google.com <cl...@google.com> #12
Fixed internally, available in navigation-2.9.0-alpha04
ap...@google.com <ap...@google.com> #13
Project: platform/frameworks/support
Branch: androidx-main
Author: Clara Fok <
Link:
Update non-reified clearBackStack and popBackStack
Expand for full commit details
Update non-reified clearBackStack and popBackStack
Added <T : Any> type parameter to the API
Test: existing tests
Bug: 381938808
Bug: 363225480
Relnote: "non-reified clearBackStack and popBackStack expects route from KClass<T> instead of KClass<*>"
Change-Id: I4d7436075cb46c8664ab670be483768e1528f17d
Files:
- M
navigation/navigation-runtime/api/current.txt
- M
navigation/navigation-runtime/api/restricted_current.txt
- M
navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerRouteTest.kt
- M
navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
Hash: ae333139fec0719656bbf0f81943a6ee9e68a096
Date: Tue Dec 03 17:11:54 2024
pr...@google.com <pr...@google.com> #14
The following release(s) address this bug.It is possible this bug has only been partially addressed:
androidx.navigation:navigation-runtime:2.9.0-alpha04
Description
Component used: Navigation Version used: 2.8.0-beta07
Currently, the back stack can be popped using the route class as a key via:
inline fun <reified T : Any> popBackStack(...)
This is un-callable is scenarios where the route class is unknown at compile time. My current workaround is using the library-internal
KSerializer<T>.generateHashCode()
on the route class and providing this as the ID topopBackStack()
- similar to what the reified method above does internally.It'd be useful to expose this functionality by adding
popBackStack(route: KClass<T> ... )
. I've noticed that a number of other nav API methods are overloaded in this manner.Note: I've seen
fun <T : Any> popBackStack(route: T, ...)
, but it considers args and is not purely ID-based.