I have navigation problem. app has 3 screens 1st -...
# compose
m
I have navigation problem. app has 3 screens 1st -> list of items 2nd -> item details 3rd -> gallery of item images I use compose navigation component version
2.4.0-alpha05
and am navigating from 1st to 2nd screen like this:
Copy code
navController.navigate("$route/${id.value}")
and routes are defined like so:
Copy code
@JvmInline
value class Routes(val route: String) {
    companion object {
        val Home = Routes("home")
        val ItemDetails = Routes("item_details/{id}")
        val ItemGallery = Routes("item_gallery")
    }
}
I access that
id
parameter inside
ViewModel
Copy code
savedStateHandle.get<String>(ARG_ITEM_ID) // ARG_ITEM_ID = "id", same as route arg
when I go from 1st screen, list of items, to 2nd, details, it works fine BUT when I go from details to gallery and press system back button
ARG_ITEM_ID
is
null
. it works fine with navigation version
2.4.0-alpha04
i
So how do you go from details to gallery? The ViewModel of your item details would still exist, so anything you do in
init
(which would the appropriate place to read the ID from the
savedStateHandle
) shouldn't be done again when you return to that previous destination
m
yes am doing it inside
init
but it crashes. that’s weird. I go from details to gallery with
navigate(route_string)
. when I go back details
ViewModel
is recreated
I’ve set up the logs and it’s hitting
init
even when going back
ViewModel
is annotated with
@HiltViewModel
and created with
hiltViewModel()
function
Copy code
const val hiltNavigation = "1.0.0-alpha02"
i
That seems wrong. If you can reproduce it in a sample project, I'd love to take a look if you could attach it to an issue: https://issuetracker.google.com/issues/new?component=409828
👍 1
That way we can confirm if it is already fixed for alpha06 or get a fix in
👍 2
m
I will create sample project
in my sample project everything works fine 😕. I will do some more digging
i
Do you have some custom back behavior (i.e., a
BackHandler
or overriding
onBackPressed()
in your activity)?
m
no. but am passing
ViewModel
from the details screen to the gallery
Copy code
composable(Routes.Gallery.route) {
    val ItemDetails = navController.previousBackStackEntry!!
    val viewModel = hiltViewModel<ItemDetailsViewModel>(itemDetails)
    Gallery(viewModel = viewModel)
}
can this be a problem?
I didn’t do that in the sample but it’s in the original code. I will try in sample now
yes that’t the problem @Ian Lake
am I doing it wrong or it’s a bug?
Copy code
androidx.hilt:hilt-navigation-compose:1.0.0-alpha03
androidx.navigation:navigation-compose:2.4.0-alpha05
com.google.dagger:hilt-android:2.37
com.google.dagger:hilt-android-compiler:2.37
i
Can you wrap your
previousBackStackEntry
call in a
remember
?
Keep in mind that with animations, your destination will continue to be recomposed as it is animating out. That means
previousBackStackEntry
starts pointing to your
Home
destination
Which obviously doesn't have any arguments like the ID
I suspect that by remembering the entry, you won't requery it every time you recompose (i.e., every frame of the animation), but just once (when it is correctly your ItemDetail screen)
m
“Which obviously doesn’t have any arguments like the ID”. I understand but it should not create new one when one already exists?
with navigation-compose:2.4.0-alpha04 and hilt-navigation-compose:1.0.0-alpha03 and 02 everything works
about animations and recomposition. that’s interesting. what about animating in? will it still recompose during animation?
wrapping
previousBackStackEntry
in
remember
works. it’s not crashing now. thank you very much!
is this happening in
2.4.0-alpha05
because it introduced
fade
as default animation which wasn’t the case in
2.4.0-alpha04
?
i
Correct. In the old world, you'ld only recompose once, then immediately disappear as soon as the NavController's state changed
What is happening in your code is that you have popped the back stack. At that point,
currentBackStackEntry
is now ItemDetail and
previousBackStackEntry
becomes Home
Which means you aren't 'recreating' the ViewModel attached to ItemDetail, you're attempting to create a brand new ViewModel scoped to Home
Which is why the remember works - now, you've 'cached' your
previousBackStackEntry
entry over recompositions so that it always points to ItemDetail
(You'd actually get a similar problem if you navigate from Gallery to somewhere else - your
currentBackStackEntry
would become your new destination and
previousBackStackEntry
would become Gallery)
m
I understand. great explanation. thank you very much Ian