https://kotlinlang.org logo
#compose
Title
# compose
t

Tim Malseed

07/19/2022, 12:33 AM
Me again. How exactly does one scope, say, a repository, to the navigation graph using navigation-compose?
The guide to app architecture recommends doing this:
If the class’s responsibility is crucial for the whole application, you can scope an instance of that class to the
Application
class. This makes it so the instance follows the application’s lifecycle. Alternatively, if you only need to reuse the same instance in a particular flow in your app—for example, the registration or login flow—then you should scope the instance to the class that owns the lifecycle of that flow. For example, you could scope a
RegistrationRepository
that contains in-memory data to the
RegistrationActivity
or the navigation graph of the registration flow.
(emphasis mine)
I tried creating a custom Hilt Component, let’s call it
NavGraphComponent
, and a
NavGraphComponentManager
- the idea, I think, is you inject the component manager, and then you can pass in, say, a route, or graph, or something - and the component manager will decide if the dependency should be rebuilt. Then, when injecting dependencies that are provided by the component, you get an existing instance, or a new one depending on the internal logic of that component manager. So, somehow the component manager should have enough knowledge to decide if you need a new instance of your repository, based on whether the nav graph has changed.
It’s a lot of pieces to wire together.. I ended up using a CompositionLocal to provide the ComponentManager to my composables. And then somewhere, I have to make the ComponentManager aware of the nav graph, and have it rebuild the component when the graph changes.. I didn’t actually get there in the end 😞
s

Stylianos Gakis

07/19/2022, 12:13 PM
Idk if this helps you but for a pure compose impl without hilt: You can see I’m using this, here and here, to get a NavBackStackEntry of the parent route to both of these destinations. That allows the ViewModel to be the same one for these two destinations.
t

Tim Malseed

07/19/2022, 12:50 PM
Thanks Stylianos. I’m OK with sharing a ViewModel between two destinations - and there’s even an example for how to do this with Hilt. What I’m looking for here is to scope a repository to the navigation graph
I’ll have a look at your implementation and see if I could use a similar pattern for a repository though
Oh, it looks like perhaps that repository is private?
s

Stylianos Gakis

07/19/2022, 12:52 PM
Oh I am sorry I completely misunderstood it then yes.
And yeah I just realized we got that repo as private 🤦‍♂️ I thought it was public, completely MB again lmao
t

Tim Malseed

07/19/2022, 12:52 PM
No worries 🙂
I’m still interested in how you manually scope a ViewModel to your NavGraph?
s

Stylianos Gakis

07/19/2022, 1:00 PM
Well this is embarrassing, I provided negative help if anything 😂 To at least try and help a bit more, I see that in Hilt there is the @ViewModelScoped
ViewModelComponent
which I suppose if you provide something using that component and you get it into your NavGraph scoped ViewModel, the Repository should also be scoped appropriately no? As far as the scoping to the NavGraph it’s a matter of providing a different owner to the
by viewModel(owner = navController.getOdysseyScopedNavBackStackEntry())
call with
Copy code
private fun NavController.getOdysseyScopedNavBackStackEntry(): NavBackStackEntry {
    return getBackStackEntry(MainScreen.Odyssey.route)
}
And MainScreen.Odyssey.route is the string of the parent route of the destinations. Here’s the source code. I was linking into.
59 Views