1
votes

I am getting this error code while going through Android Studio 3.0 Development Essentials. "Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type Intent?". Not sure why. The above code is what I am currently working with and "Intent" had automatically generated a question mark. The bottom code is what is shown in the book.

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    if ((requestCode == request_code) && (resultCode == Activity.RESULT_OK)) {
        if (data.hasExtra("returnData")) {
            val returnString = data.extras.getString("returnData")
            textView1.text = returnString
        }
    }
}

Code in book

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
    if ((requestCode == request_code) && (resultCode == RESULT_OK)) {
        if (data.hasExtra("returnData")) {
            val returnString = data.extras.getString("returnData")
            textView1.text = returnString
        }
    }
}
4
What version of Kotlin are you using and what version is the book mentioning? Could it be that the method signatures changed? In Fragments the signature is (as of today) override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { so it's an Optional.Martin Marconcini

4 Answers

3
votes

The error, if you come from Swift, is basically because the signature:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {

Indicates that the parameter data of type Intent? is of type "Nullable" (Optional in Swift). Meaning you have to dereference the Optional first.

In Kotlin (like in Swift), you do so with the ? mark.

if (data?.something)

Means that if data is null, or something is false/null (depending on its type), then the if will not enter its block.

same for:

if (data?.something && data?.somethingElse)

This will not crash if data is null and will only pass the condition if both something and somethingElse are true (or non-null for non-primitives).

The book is probably referencing an old version of Kotlin or the Kotlin-Android plug-in where the Intent received is not optional and therefore cannot be null.

All this is better explained in the Kotlin Nullability chapter :)

0
votes

Your intent is nullable, you have to access its properties using ? or check for null before using it:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    if (data != null && (requestCode == request_code) && (resultCode == Activity.RESULT_OK)) {
        if (data.hasExtra("returnData")) {
            val returnString = data.extras.getString("returnData")
            textView1.text = returnString
        }
    }
}
0
votes

You could leverage smart casts, what in this case automatically would cast Intent? to Intent if you explicitly check for data != null before you use data.

Otherwise just insert null-safe method invocations like data?.hasExtra("returnData")) where needed.

0
votes

This is because you're accessing hasExtra on the data variable without checking to see if the data variable is non-null since you declared data as nullable (aka with the ? appended to the Intent), hence you get that error. The solution would be one of the following:

  1. Add a safe operator (?.) *(recommended): data.hasExtra(/* ... */) -> data?.hasExtra(/* ... */))
  2. Add a non-null operator (!!) *(not recommended unless you know that the value will always be non-null)*: data.hasExtra(/* ... */) -> data!!.hasExtra(/* ... */)
  3. Add a condition to check if data is non-null before continuing: data.hasExtra(/* ... */)-> data != null && data.hasExtra(/* ... */) (Note: Kotlin will automatically treat the value of data to be non-null for code inside the data != null condition)