Sharas
Sharas

Reputation: 2135

Android navArgs clear on back

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.

Upvotes: 15

Views: 6325

Answers (5)

Mmr100
Mmr100

Reputation: 1

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

Upvotes: 0

Abhishek
Abhishek

Reputation: 173

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

Upvotes: 0

muetzenflo
muetzenflo

Reputation: 5682

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()   
}

Upvotes: 8

Matthew Fisher
Matthew Fisher

Reputation: 143

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

Upvotes: 12

Juanjo Berenguer
Juanjo Berenguer

Reputation: 789

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.

Upvotes: 1

Related Questions