Android navArgs clear on back

Viewed 3121

Is there a way to clear navArgs after using them? I have fragment A that opens fragment B with navArgs, then I navigate to fragment C and the user presses back, so fragment B is opened with the same navArgs and I don't want that.

Is there a way to navigate back to fragment B without the navArgs?

Thanks.

6 Answers

The answer suggested by Juanjo absolutely does work. The only caveat is that you can't use the navArgs property delegate to get at them since it's wrapped Lazy. Instead you just go through the underlying arguments bundle.

For example, in FragmentB

// don't need to pull in the navArgs anymore
// val args: FragmentBArgs by navArgs()

override fun onResume() {
  when (FragmentBArgs.fromBundle(arguments!!).myArg) {
    "Something" -> doSomething()
  }
  // clear it after using it
  arguments!!.clear()
}

// now they are cleared when I go back to this fragment

Calling arguments?.clear() is not sufficient. Reason for that is that the navArgs() delegate holds all arguments in a local cached variable. Moreover, this variabel is private:

(taken from NavArgsLazy.kt)

private var cached: Args? = null

override val value: Args
    get() {
        var args = cached
        if (args == null) {
            ...
            args = method.invoke(null, arguments) as Args
            cached = args
        }
        return args
    }

I also find this approach pretty stupid. My use-case is a deeplink that navigates the user to a specific menu item of the main screen in my app. Whenever the user comes back to this main screen (no matter wherefrom), the cached arguments are re-used and the user is forced to the deeplinked menu item again.

Since the cached field is private and I don't want to use reflections on this, the only way I see here is to not use navArgs in this case and get the arguments manually the old-school way. By doing so, we can then null them after they were used once:

val navArg = arguments?.get("yourArgument")
if (navArg != null) {
  soSomethingOnce(navArg)
  arguments?.clear()   
}

I think you could to remove the arguments when your fragment B will be destroyed

You could use the method getArguments().clear(); in onDestroyView() or whenever you want to clear the arguments in your fragment.

You can simply do navArgs.toBundle().clear()

if you only want to remove one Argument from navArgs you could use

requireArguments().remove("yourArgument")

Remember to use Android:defaultValue inside declaration on your navigation Xml, if you don't do it your app will crash because it won't find the argument previously declared

Simply, use navArgs only in onCreate methods, set viemodel variables there before going to Activity C and use them instead of navArgs in other methods.

Related