Kotlin Bundle.putString not explicitly adding "String" but instead is "String?"

Viewed 1367
val args = Bundle()
args.putString("type", details.type)

navigator.navigate(context!!, findNavController(), Destination.TYPE, args)

I am quite confused as to why in the receiving fragment when I go to access the arguments I have passed through it is responding with...

val type: String = arguments.getString("type")

The arguments.getString is all underlined red and says "Required String Found String?" But how when I called method "putString"?!?

It is resulting in text not being rendered in the new fragment and I assume this is a nullability issue.

4 Answers

It's a matter of knowledge that is available in the receiving Fragment.

The Fragment is not aware of how its arguments were created (or modified) so it has to assume the "type" key you're looking for might not be in the arguments Bundle. That's why it returns a nullable (String?) result (the null value would mean absent in arguments).

Your fragment might be created in many places in your app and its arguments might have been modified in many places. We have no way of tracking that.


There are different solutions for this problem, depending on your approach in other parts of the code and how "confident" you are in creating of your Fragment.

I would usually choose a solution in which I assume setting the type is mandatory. Therefore if the type is absent - I fail fast. That would mean the Fragment was misused.

val type: String = arguments!!.getString("type")!!

The code above will crash if either:

a) arguments weren't set, or

b) String with type wasn't put in the arguments Bundle.

You are right, that is a : null ability issue.

First you should be sure if you are expecting a value, so try adding "?" or "!!", i would recommend "?", or go with the block of if {} else

To read the string safely you can use:

val type: String = arguments?.getString("type").orEmpty()

The orEmpty call at the end ensures that a valid String is returned even if either arguments or getString() returns null.

The method signature for getString() returns a nullable String. This is because at compile time, the compiler can't know if the value exists in the bundle or not. You will have the same issue when retrieving anything from any Map.

If you know for certain that the value in the bundle or map should exist at the time you call getString(), you can use the !! operator. That's what it's there for. When you know something should always be there, it is appropriate to want an exception to be thrown (in this case KNPE) if it's not there so you can easily find any programming error during testing.

isEmpty() or ?.let aren't helpful in this particular case because they would just be masking a programming error and making it harder to discover or debug.

Related