Any ETA on official navigation/backstack? :sweat_s...
# compose
d
Any ETA on official navigation/backstack? 😅
i
https://issuetracker.google.com/issues/161472731 is the issue to star for progress updates
👍 4
j
@Ian Lake is it available in navigation 2.4 in the androidx snapshot repo?
i
It is a separate
androidx.compose.navigation
artifact group at the moment
But yes, there is a snapshot available in pre-dev level of quality
👍 3
j
I have a few questions: • Where can I give feedback about improvements for androidx.dev web? (actually, if I want to find
ui/androidx/compose/navigation
, I have to click "next page" a few minutes, and in the url I can't put the page number too because it is using a token • I didn't see samples with args, so I guess they are not supported at this moment
i
a
Is there a way to use a Crossfade with the current implementation of NavHost?
i
No, that's one of the topics we're going to be working on prior to any release
👍 1
s
Injection into a Composable function? Please no
👍 1
😄 1
i
Navigation in Compose supports ViewModels at the screen level. Navigation doesn't care/control/have anything to do with where you get your ViewModel Factory from, Hilt or not
❤️ 1
a
Hmm ok, maybe I have to check again. Currently he is searching for an empty constructor in my ViewModels. It seems that the HiltViewModelFactory was not used
i
Sounds like it isn't using your Hilt provided factory at all. Have you tried the instructions in the Hilt guide? https://developer.android.com/training/dependency-injection/hilt-jetpack#viewmodel-navigation
a
Jup. ViewModel Injection outside of compose works fine. Don’t know if there is a Problem with NavBackStackEntry within the androidx navigation library. The getDefaultViewModelProviderFactory created the SavedStateVieeModelFactory
In NavHost compose the ViewModelStoreOwnerAmbient provides the currentNavBackStackEntry. I thought that would cause these problem
j
@Ian Lake so if I annotate the activity as EntryPoint, hilt should work with compose ootb (using the ViewModel function inside the composable)?
i
More official documentation on Hilt+Compose is still to come, but if you use the containing Activity/Fragment's
defaultViewModelProviderFactory
and Compose's viewModel function, then it'll certainly use Hilt's factory
👍 1
Assuming your containing Activity/Fragment is correctly set up in Hilt land (i.e., as an EntryPoint)
That's all independent of Navigation
a
Hmm I did all of this. I will try it tomorrow again.
@Ian Lake Tried it again.  Test 1 (worked): val viewModel: MyViewModel by viewModels() in the MainActivity injects the ViewModel with Hilt.  Test 2 (worked): val viewModel: MyViewModel = viewModel() within compose Test 3(crash): val viewModel: MyViewModel = viewModel() within NavHost. NewInstanceFactory tries to create an instance. No zero argument constructor.
i
You did read the docs I linked above right? You have to pass in the factory when in Navigation
Hilt only does things at the Activity or Fragment layer, it has no idea about the Navigation layer, so when you create ViewModels that are scoped at the Navigation layer, you need to be explicit that you want to pull a ViewModelProvider.Factory out from your Activity/Fragment
This is part of what the Hilt team is looking at for best practices for Hilt in Compose
a
You were right. didn’t read correctly. Worked with using the defaultViewModelProviderFactory from the Activity. But now it crashes, when i enter a subview second time. SavedStateProvider with given key is already registered. Think i am still doing something wrong.
2
i
50/50 chance that it isn't your fault too. There's a reason that Navigation and Hilt isn't part of the current alpha release yet - still more to do 😄
👍 1
m
@Alexander Karkossa did you ever solve this?
a
Hey, this was a while ago, so I’ll try to get it together once. I found a way to use
Hilt
`ViewModel`s in
NavHost
, but I haven’t checked for a long time to see if it works without that workaround in the meantime.
Copy code
class ViewModel(
  private val repository: Repository,
) : ViewModel() {

}

class ViewModelFactory(private val context: Context) : ViewModelProvider.Factory {

  @EntryPoint
  @InstallIn(ApplicationComponent::class)
  interface ViewModelProviderEntryPoint {
    fun repository(): Repository
  }

  @Suppress("UNCHECKED_CAST")
  override fun <T : ViewModel?> create(modelClass: Class<T>): T {
    val provider = EntryPointAccessors.fromApplication(context, ViewModelProviderEntryPoint::class.java)
    return ViewModel(
      repository = provider.repository(),
    ) as T
  }
}

@Composable
fun ComposeView(
  modifier: Modifier = Modifier
) {
  val viewModel: ViewModel = viewModel(factory = ViewModelFactory(AmbientContext.current))
}