Почему свойства ненулевого типа класса, полученные из WeakReference.get (), изменяются на nullable - PullRequest
0 голосов
/ 07 июня 2018

Я пытаюсь написать обработчик в действии, для которого требуется ссылка на действие.Если я напишу так:

class MainActivity : AppCompatActivity() {
    private val mHandler = MainActivityHandler(this)

    class MainActivityHandler(val activity: MainActivity) : Handler() {
        override fun handleMessage(msg: Message?) {
            when(msg?.what) {
                MSG_CHANGE_TEXT -> {
                    activity.tv_logged.setText(R.string.title_main)
                    activity.mHandler.sendMessageDelayed(obtainMessage(SOMETHING), 3000)
                }
                // ...
            }
        }
    }
}

Этот код компилируется и работает как положено.Но если я попытаюсь передать слабую ссылку на активность, подобную этой

class MainActivity : AppCompatActivity() {
    private val mHandler = MainActivityHandler(WeakReference(this))

    class MainActivityHandler(val activityRef: WeakReference<MainActivity>) : Handler() {
        private val activity
            get() = activityRef.get()

        override fun handleMessage(msg: Message?) {
            when(msg?.what) {
                MSG_CHANGE_TEXT -> {
                    activity?.tv_logged.setText(R.string.title_main)
                    activity?.mHandler.sendMessageDelayed(obtainMessage(SOMETHING), 3000)
                }
                // ...
            }
        }
    }
}

Теперь компилятор жалуется, что tv_logged и mHandler относятся к типу приемника, допускающему обнуляемый тип, и ему необходимобыть доступным с помощью?Я могу понять, что val activity: MainAcitivity? внутри обработчика имеет значение NULL, потому что оно исходит из WeakReference.get (), но почему свойства в MainActivity также могут иметь значение NULL?

Ответы [ 2 ]

0 голосов
/ 07 июня 2018

Я понял это, когда прочитал весь текст на https://kotlinlang.org/docs/reference/null-safety.html#safe-calls

Это не имеет ничего общего с WeakReference, как я и подозревал.Это происходит потому, что оператор безопасного вызова возвращает обнуляемый тип даже при доступе к необнуляемым свойствам типа.(На самом деле документ не указывает это так явно и ясно.)

0 голосов
/ 07 июня 2018

Это потому, что тип возвращаемого значения activity?.tv_logged (при условии, что он TextView), TextView?,В Kotlin docs, где предлагается альтернатива проверке null через if условие

Ваш второй вариант - оператор безопасного вызова, написано?b? .length Возвращает b.length, если b не равно нулю, и ноль в противном случае.Тип этого выражения Int?.

Чтобы выполнить определенную операцию только для ненулевых значений, вы можете использовать оператор безопасного вызова вместе с let:

 activity?.let{ //access activity via `it`}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...