How to use SavedStateHandle and navigation Safe Args

Viewed 5581

I have two options to pass data between fragment, the navigation's safe args and viewModel's SavedStateHandle, what's the difference between them and how to use them in the correct place?

2 Answers

If you are using hilt you can wrap the incoming arguments in the fragment (and other components) like so

open class BaseFragment : Fragment() { // Inherit your fragment from this

    override fun setArguments(args: Bundle?) {
        if (args != null) {
            if (args.getBundle(BUNDLE_ARGS) != null) {
                super.setArguments(args)
            } else {
                super.setArguments(Bundle(args).apply {
                    putBundle(BUNDLE_ARGS, args) // Wrap the arguments as BUNDLE_ARGS
                })
            }
        } else {
            super.setArguments(null)
        }
    }
}

and then for the view model, you can inherit from something like that

open class ArgsViewModel(private val savedStateHandle: SavedStateHandle) : ViewModel() {

    val arguments get() = savedStateHandle.get<Bundle>(BUNDLE_ARGS)

    @MainThread
    inline fun <reified Args : NavArgs> navArgs() = NavArgsLazy(Args::class) {
        arguments ?: throw IllegalStateException("ViewModel $this has null arguments")
    }
}

And then use it just like you would use safe args

class FooViewModel @ViewModelInject constructor(
    @Assisted savedStateHandle: SavedStateHandle
) : ArgsViewModel(savedStateHandle) {

    private val args: FooFragmentArgs by navArgs()
}
Related