Is there any examples of using NavController withi...
# compose
s
Is there any examples of using NavController within Hilt Viewmodel and also using SaveHandler for handling Process restart? It would be so much simpler if there is a way to merge all the remember*State with State in ViewModel.
t
I’ve a small app here that matches the above requirement. Basically, all you’ve to do is inject the
SavedStateHandle
through the viewModel’s constructor and use
SavedStateHandle#get<T>(yourKey)
to access the data.
AFAIK, you don’t even need to pass the navEntry to
hiltViewModel
method
☝️ 1
f
navigation arguments are automatically put into the ViewModel's SavedStateHandle so you can read the values from there
and recreate your screen after process death
s
Sorry, i meant i want to perform navigation within viewModel.
t
I’d recommend @Joe Birch’s article on modular navigation, Also you can take a look at @cb tivi app which uses a different approach.
s
@theapache64 i think, Tivi doesn't perform navigation within ViewModel.
t
Yeah, you’re right. tivi doesn’t trigger navigation from viewModel. it hoist the event to the parent composable where it has access to
navController
. I was telling why don’t you mix it 😄 . Put a
state
variable in viewModel, something like
onNavigateToSplash = State<Boolean>
, observe it in the composable, and hoist the event from there? 🤔 it’d work, but doesn’t sound like a good approach 😄 isn’t it? 😬
pls look at @Joe Birch’s article.IMO, there’s a lot of advantage on using that approach.
👍 1
f
I use a channel converted into a flow to send navigation events from the ViewModel to the screen
state means it's sticky which is a problem if you navigate forward
s
@Florian Yeah, I'm also doing the same with
Channel
and collect in
LaunchedEffect
but it would be much simpler if we can inject NavController in ViewModel and directly call navigate, I think it's is possible with NavController but we lose the state after process restart which rememberNavController do.
f
@zhuinden handles navigation in the ViewModel, maybe he can tell you more
i
Can you explain your case for navigating from a ViewModel? We had an internal discussion about that exact topic this last week and came to conclusion that doing that is always the sign of a bigger issue with how you handle events and cancellation correctly. It would be good if you could explain what is actually triggering your navigation event (from and action the user does or from something changing elsewhere in your app)
s
I have a list of Language learning Packs that users can Tap on and each Pack can have Different statuses like Free, 10 Coins, Get, and Open and I have a function in ViewModel e.g ProcessPack, and depend on the status I Perform some operations like inserted to DB and in some cases, I send Event to Composable Screen to Move to different Screens if User doesn't have Coins available, etc.
i
So what happens if the user hits the system back button while process pack is still running? Is the operation supposed to cancel? Or should the processing continue to happen even if the UI isn't there anymore? If the user does exit your app (say, they hit the home button or get a phone call, etc.) before processing completes and your whole process were to die before your UI is actually shown again, how do you recover the result of that processing (let's say the processing completed while your app was in the background because your answer to the above cancellation question was that it shouldn't cancel)?
s
So what happens if the user hits the system back button while process pack is still running? Is the operation supposed to cancel? Or should the processing continue to happen even if the UI isn't there anymore? Depend on the Pack status if it is OPEN, ViewModel directly sends an event to Composable to move to PackDetails, but if it is GET I add the Pack to DB and after that ViewModel send an event to move to the next screen, but if the user press back before processing completes it keeps on running because it is on the Repo layer and if the process killed while app in the background, ViewModel created again for that Composable and in the init block app observe again form DB but since Pack was not added I still show as GET.
i
But you've already marked it in the database, but didn't redirect them to the next screen to get more coins. How do you tell those cases apart?
1
s
GET means pack is not added to DB, so if user click on pack with GET status and press back, next time they come on screen it will show as OPEN.
Basically, i don't want to navigate when App is in background. Just status will change, All that is working fine for me but i feel it would much simpler if navigation event can be performed by Viewmodel.