In `nav3` when I push say `data object Profile : N...
# compose
u
In
nav3
when I push say
data object Profile : NavKey
, once I get the matching profile screen & it's viewmodel displayed as expected (and in the viewmodel I have a timer ticking every second and incrementing counter) When I push
Profile
again on top of it, so backstack is
[Profile, Profile]
I oberve the top screen is the first profile, not the latest profile (juding by the counter) is this a bug in
nav3
?
a
How are you creating the view model? If I recall correctly, you'll need to provide a
key
to something like
hiltViewModel
if you need more than one insurance of the same view model for different/repeated destinations.
u
I dont use hilt, but I dont see the entry lambda called at all, its not a viewmodel issue
If i change the key from data object to a data class with random int as value then it behaves as expected 🤷‍♂️ hope this isnt desired
r
@ursus Without code, we can't help :v
u
Copy code
@Serializable
data object Profile : NavKey

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MaterialTheme {
                val backStack = rememberNavBackStack(Profile)

                NavDisplay(
                    backStack = backStack,
                    onBack = { backStack.removeLastOrNull() },
                    entryProvider = entryProvider {
                        entry<Profile> {
                            val depth = backStack.count { it == Profile }

                            Column(
                                modifier = Modifier.fillMaxSize(),
                                verticalArrangement = Arrangement.Center,
                                horizontalAlignment = Alignment.CenterHorizontally
                            ) {
                                Text(text = "Hello world")
                                Text(text = "Profile count on stack: $depth")

                                Button(
                                    onClick = dropUnlessResumed {
                                        backStack.add(Profile)
                                    }
                                ) {
                                    Text(text = "Push Profile again")
                                }
                            }
                        }
                    }
                )
            }
        }
    }
}
i
Every NavEntry has a
contentKey
- that is what the state of the screen is tied to. If your keys are
data class Profile(id: String)
, then you'll get a different
contentKey
for each unique
id
and unique state for each instance of a given
id
. If you use a
data object
, then you'll get the exact same
contentKey
for every position that key is on the back stack, so you should expect them all to share the same state, that is working as intended
u
Guess it makes sense if I think about it as a library developer, but I'm almost certain non expert users won't expect this, i.e. having a backstack of
[a, b, a, b]
to get only 2 viewmodels in memory
i
I think the most obvious thing is you encode your information into your keys like all of our examples do and only use objects when they are actually singletons. I'm not sure why you'd use a
data object
to model something you'd put multiple times on the back stack in the first place, but maybe I'm missing something on how you got yourself into this in the first place?
u
hmm you're right, it's just a habit I have from modeling sealed hierarchies of data so you're saying to use
class Profile : NavKey()
, right?
i
it needs to have a different
contentKey
, so you'd need to add something in there that is unique to what profile you want to display - the default
contentKey
of a NavEntry is just
key.toString()
which is great for a
data class
, but not useful if you don't have anything different in each instance
and yes, adding a UUID to your key is a perfectly valid way to make sure each instance is unique
u
wont toString print the identity for the bare
class
and therefore work as well? generating random uuids seems like a overkill
i
a
data class
's
toString()
just outputs all of the properties of the class
u
i know, i mean
class Profile
i
it needs to be something that is stable across process death and recreation - otherwise you won't get your state back
e.g., the state is tied to a
contentKey
of
0x12341234
but after a process death you get a new
contentKey
of
0x56785678
== no state restored
u
that however means all navkeys, even data class keys needs to be uuid'd as well, don't they? Since this
[A("123"), B("321"), A("123")]
would yield the same effect
i
You can encode whatever you want into your keys with whatever level of uniqueness your app needs
(your app doesn't need
Profile("123")
to be different from
Profile("123")
, you're overthinking things)
u
probably not, I'm just prototyping now and looking at all the ways one can shoot themselves in the foot I was naively expecting it to always yield a new screen anyways, that means singleton keys (
data object
) are fine, doesn't it?
i
I would expect a
data object
screen for things like your
Home
screen or a
Login
screen, absolutely
u
I'm not sure why you'd use a
data object
to model something you'd put multiple times on the back stack in the first place,
so then I probably misunderstood this
but okay it's clear now, thank you!
👍 1