When using adaptive layout in nav3, I'm getting an...
# compose
m
When using adaptive layout in nav3, I'm getting an exception
Key FooRoute(...) was used multiple times
because the list/detail can sometimes show the same content on both sides. This is because of the nature of navigation in my app - just think of a cyclic graph. How to overcome this? One idea, I guess, is to first check if the route is already in the backstack and, if so, just pop to that.
i
The first question is: do you really want the user to see two exactly identical screens side by side? If no, then you're correct that this is a back stack problem and you should modify how you update the back stack to avoid that case entirely. If you don't think they are exactly identical screens (they just happen to have the same key), then your issue is in how you've defined your key: maybe you've defined some side channel that is an additional key to the "uniqueness" of the screen that really should be encoded in your key class. If yes and you really do need users to see copies of the same screen, then you can make any key unique by adding a UUID property to the key: then even two instances that are the same by every other key are going to be unique and can be displayed side by side
m
Thanks Ian. There is a practical reason why you might want to see two identical screens side by side; consider a long LazyColumn - you might want to see one part on one side, and another part on the other. So, I'm kind of curious what is the reason why there can't be two identical routes in a layout? Now I've had a little time to think about it, in my case, I'm adding a route onto a backstack where the top route is the same, so in my case it makes sense to just stick with the current backstack instead.
i
SaveableStateProvider forbids it - it just immediately crashes if you have the exact same state in two places in the hierarchy. And it is the
contentKey
is that key
m
Ok, I see. I'm also curious about any drawbacks from adding UUID to route
i
your savedInstanceState will be just a little bit bigger than it would be otherwise and you won't be able to assume equality (e.g.,
backStack.contains(newKey)
would always return false) if you did want to do fancier back stack logic
but it is exactly the tool to use if you really do want every instance to be unique and have their own unique state
m
Would that include things like scroll state? For example, if a backstack contains the same route multiple times (though not in the same layout).
i
all of the state is keyed to the
contentKey
of the entry, so multiple entries with the same
contentKey
would all share the same state - the same scroll position, the same ViewModels, etc.
m
Hmm, in that case it sounds like I definitely want to use UUID. Because you want to be sure to return to a screen in the state you left it. Not in the state you left a screen of the same key.
i
sure, you have full control over how you model your keys and your back stack, so whatever makes sense for your exact use case
m
Should it be an error if the same key exists multiple times in the backstack? If the same key exists twice in the same layout then it will lead to an error. Otherwise, not, but does it ever make sense to have two different backstack entries sharing the same state? I think the issue here is that it's very easy to end up with the same key duplicated in the backstack. Even though it can be explained why this might lead to errors or unexpected state behavior, I wonder if there's a better way. A backstack is a
List
and so this kind of implies that items can appear more than once.
👍 1