Reputation: 2346
I have this scenario in which the user clicks on a button in composable A then selects an item from the list from composable B and selects another item from the list from composable C.
My problem is when I select an item from screen C I want to navigate back to screen A with whatever I selected in B & C. But popBackStack doesn't work when arguments are given.
Here is the code,
navController.popBackStack(route = Screen.SelectPlan.route + "?regionId=${region.id}&operatorId=${operator.id}")
Right now, I see that popBackStack does take a route argument, but converts it to a hashcode to navigate back instead of creating a Uri-like navigate function.
Upvotes: 10
Views: 6553
Reputation: 63
I encountered the same issue and have just discovered the solution for myself.
When you navigate to a destination, using args like so:
val arg1 = "someValue"
val arg2 = "someOtherValue"
navController.navigate("Destination/$arg1/$arg2")
... this route
is stored in the newly created backstack entry, not with the values of those args, but with their names as assigned in your NavHost
.
Assume my NavHost
contains a composable
with a route of Destination/{arg1}/{arg2}
.
If the .navigate()
call in my previous example is executed, an entry will be added to the backstack with this route Destination/{arg1}/{arg2}
, not this route Destination/someValue/someOtherValue
.
You didn't provide your NavHost
in the post, but if you replace the values of those args in the call to .popBackStack()
with their names you assign in your NavHost
, it should work for you.
Upvotes: 5
Reputation: 97
This is indeed a bug and it bothered me for a long time. After a long time of research and reading the navigation
source code, I wrote my own extension function NavController.popBackStack
to fix this problem. It is tricky but works for me. Also note that this version of extension function does not support the inclusive
and saveState
options (due to the current navigation API limitation), so you can't restoreState
when you return to the current destination.
import android.content.Intent
import androidx.navigation.NavController
fun NavController.popBackStack(route: String): Boolean {
if (backQueue.isEmpty()) {
return false
}
var found = false
var popCount = 0
val iterator = backQueue.reversed().iterator()
while (iterator.hasNext()) {
val entry = iterator.next()
popCount++
val intent = entry
.arguments
?.get("android-support-nav:controller:deepLinkIntent") as Intent?
if (intent?.data?.toString() == "android-app://androidx.navigation/$route") {
found = true
break
}
}
if (found) {
navigate(route) {
while (popCount-- > 0) {
popBackStack()
}
}
}
return found
}
Upvotes: 2
Reputation: 1929
Try put "/" instead of ?
navController.popBackStack(route = Screen.SelectPlan.route + "/regionId=${region.id}&operatorId=${operator.id}")
Upvotes: 0