0

I have the following function in a Kotlin class:

private fun raiseResponse(ex: Exception, resObj: JSONObject) {
    if (_activity == null || _responseHandler == null) return

    _activity.runOnUiThread {
        _responseHandler.invoke(ex, resObj)
    }
}

Where both _activity and _responseHandler are defined as:

var _activity: Activity? = null
var _responseHandler: ((Exception, JSONObject) -> Unit)? = null

However, the line that calls runOnUiThread will only compile if I use ?. instead of ..

I've tried Google searching but I'm afraid my terminology is lacking. I assumed my null check on the first line of raiseResponse was enough to ensure that the ?. was unecessary?

Luke Joshua Park
  • 9,527
  • 5
  • 27
  • 44

1 Answers1

4

First, note that the check and the usage get the value of the property twice. Since _activity is a var, it can be reassigned (potentially, by another thread) between the check and the usage. It is not null-safe to use the property value, because it can be not the value that was checked, and the compiler requires you to check the value again.

In other words, the compiler cannot smart-cast _activity to a non-nullable type.

You can fix this by storing the value in a local variable (it cannot be changed from outside, so the compiler can prove it's the same value):

val activity = _activity
if (activity == null || _responseHandler == null) return

activity.runOnUiThread {
    _responseHandler.invoke(ex, resObj)
}

Or, equivalently, use some idiom like ?.let { ... }:

_activity?.let { activity ->
    if (_responseHandler == null) return

    activity.runOnUiThread { // safe, because it is surely the same value
        _responseHandler.invoke(ex, resObj)
    }
} ?: return

See also:

hotkey
  • 140,743
  • 39
  • 371
  • 326
  • Ahh okay excellent. This makes sense, the scope of `_activity` means that it can be potentially modified after the check but before the call. I thought it might have been this but was reluctant to make a bunch of local variables before confirming. – Luke Joshua Park Jun 01 '17 at 01:27