Почему тип результата Activity.findViewById выводится как тип платформы? - PullRequest
0 голосов
/ 07 октября 2018

Я новичок в разработке под Android и Kotlin.

Я слежу за первым учебником по Android с Kotlin, и у меня есть вызов этого метода:

val editText = findViewById<EditText>(R.id.editText)

Где findViewById - этоопределяется в android.app.Activity как:

@Nullable
public <T extends View> T findViewById(@IdRes int id)

Android Studio показывает, что editText выводится как тип EditText!.Я прочитал документацию Kotlin о совместимости Java и типах платформ, но, поскольку findViewById помечен android.annotation.Nullable, который ( согласно документации Kotlin ) среди списка поддерживаемых аннотаций обнуляемости, я ожидал бы *Тип 1017 * выводится как EditText?.

Я вижу, что желаемый результат получается, если я изменяю свой код на:

val editText = findViewById<EditText?>(R.id.editText)

Но зачем это нужно и @Nullableпросто игнорируется?

Ответы [ 2 ]

0 голосов
/ 15 октября 2018

Фактическая аннотация, установленная на android.app.Activity, равна @android.annotation.Nullable.Необнуляемый аналог - @android.annotation.NonNull.Они не входят в число «аннотаций Android Nullability», которые в настоящее время поддерживаются Kotlin ( см. Документацию ), которые, скорее, объявлены в пакетах com.android.annotations и android.support.annotations.

Я открыл выпуск KT-27566 и выяснилось, что эти аннотации в настоящее время игнорируются, поскольку они сохраняют исходный код и, следовательно, они недоступны в скомпилированном байт-коде для обработки компилятором Kotlin.

Более того, согласно KT-25279 , похоже, что есть другие подобные аннотации, определенные вместо этого в пакете com.android.support, которые страдают от той же проблемы.

Я действительно не понимаю, почему Google делает такой беспорядокс аннулируемыми аннотациями (так много разных вариантов, некоторые из которых бесполезны для интеграции с Kotlin, где их полезность будет максимальной ...).

0 голосов
/ 07 октября 2018

Метод может быть обнуляемым, но спецификация вашего класса - нет.Я декомпилировал один из моих APK и обнаружил следующее.

Вот простой метод Котлина:

private fun setAppName() {
    val name = view.findViewById<TextView>(R.id.app_name)
    name.text = appInfo.appName
}

Вы можете видеть спецификацию name как TextView.

Этот метод превращается в следующее при компиляции:

private final void setAppName() {
    TextView textView = (TextView) this.view.findViewById(R.id.app_name);
    Intrinsics.checkExpressionValueIsNotNull(textView, "name");
    AppInfo appInfo = this.appInfo;
    if (appInfo == null) {
        Intrinsics.throwUninitializedPropertyAccessException("appInfo");
    }
    textView.setText(appInfo.getAppName());
}

Обратите внимание, что приводит к возвращению findViewById к тому, что вы положили в скобки.В вашем случае EditText.

По сути, этот акт все портит.Это было бы похоже на это:

val view: View? = findViewById(R.id.whatever)
val castView: TextView = view as TextView

Он эффективно обходит @Nullable из-за того, как Kotlin обрабатывает вывод типов.

...