Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass argument to detail ViewModel via navArgs

I have a screen with a RecyclerView of podcasts, where when you click one, it takes you to a detail screen for that particular podcast. Using Kodein for ViewModel injection, how can I pass the id of the podcast that was clicked from the list fragment to the detail fragment's ViewModel so that it can be fetched from an API?

The detail ViewModel is structured like this:

class PodcastDetailViewModel internal constructor(
    private val podcastRepository: PodcastRepository,
    podcastId: String = ""
): ViewModel() {
    // viewmodel stuff
}

The detail fragment looks like this:

class PodcastDetailFragment : ScopedFragment(), KodeinAware {
    override val kodein by closestKodein()
    private val args: PodcastDetailFragmentArgs by navArgs()
    private val viewModelFactory: PodcastDetailViewModelFactory by kodein.newInstance { PodcastDetailViewModelFactory(args.podcastId, instance()) }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        viewModel = viewModelFactory.create(PodcastDetailViewModel::class.java)
    }

    // other stuff
}

And this is how I'm navigating to the detail screen from the list:

private fun navigateToPodcastDetailFragment(podcastId: String) {
        val args = Bundle()
        args.putString("podcast_id", podcastId)

        val directions =
            TopPodcastsFragmentDirections.viewPodcastDetails(
                podcastId
            )
        val extras = FragmentNavigatorExtras(
            podcast_image to "podcastImage_$podcastId"
        )

        Navigation.findNavController(requireActivity(), R.id.nav_host_fragment)
            .navigate(directions, extras)
    } 

This is how I'm binding it:

bind() from provider { PodcastDetailViewModelFactory(instance(), instance()) }

I'm not sure how to bind that string parameter in the ViewModelFactory constructor, or how else to pass the data there, so any help would be much appreciated.

like image 755
Cameron Avatar asked Oct 18 '25 12:10

Cameron


1 Answers

You could use a factory for your bindings:

bind() from factory { podcastId: String -> 
    PodcastDetailViewModelFactory(podcastId, instance()) 
}

calling it on-site with:

private val viewModelFactory: PodcastDetailViewModelFactory by instance(arg = args.podcastId) 

hope this helps.

like image 55
romainbsl Avatar answered Oct 20 '25 03:10

romainbsl



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!