当我在 Kotlin 中输入视图的 name/ID 时,为什么会出现 "unresolved reference" 错误?

Why do I get "unresolved reference" error for my view's name/ID when I type it in Kotlin?

我正在严格按照教程进行操作。我在 android:id 下的布局 XML 文件中为视图命名。当我在 Kotlin 中键入该名称时,它以红色突出显示并且出现“未解析的引用”错误。

例如XMLactivity_main.xml:

<TextView
    android:id="@+id/nameTextView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>

在 Kotlin 中 MainActivity.kt:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    
    nameTextView // <-- This is highlighted red with error so I can't use it!
}

我提出这个问题是因为自从弃用 Kotlin Android 扩展以来,我已经多次看到它的变体,但它们的措辞方式各不相同,而且不太容易搜索。我认为共同因素是新的 Android 程序员遵循在弃用之前编写的教程。这些教程通常不会指定正在使用的功能称为 synthetic propertiesKotlin Android Extensions合成视图属性,或kotlin-android-extensions,并且该功能已弃用.

在 Kotlin 中通过 ID/name 直接引用视图的能力称为“综合属性”,它是名为 Kotlin Android Extensions 的项目插件的一项功能.

Google 和 JetBrains 决定弃用 Kotlin Android Extensions,这意味着他们不再支持它,并阻止您使用它。自从它被弃用后,当您在 Android Studio 中创建一个新项目时,该插件将不再包含在新项目中。因此,合成属性 在新项目中不受支持,如果您尝试使用它,您将收到“未解析的引用”错误。

2017年到2020年之间写的教程经常用到这个功能,如果没有更新,他们可能连名字都不会提,因为它被认为是理所当然的一个包含插件新项目。

Google 解释了在 this blog post 中弃用它的原因,主要有以下原因:

  • They pollute the global namespace
  • They don’t expose nullability information
  • They only work in Kotlin code

获取视图参考的快捷方式是使用 findViewById。 View 的类型应该放在方括号 <> 内。在 Activity 中,它看起来像这样:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    
    val nameTextView = findViewById<TextView>(R.id.nameTextView)

    // Now you can refer to the view using the variable
    nameTextView.setText(R.string.hello_world)
}

在 Fragment 中,您可能会在 onViewCreated 函数中使用视图,因此您必须在父视图上调用 findViewById。 (如果您需要在 Fragment 的其他地方访问它,请使用 requireView() 而不是 view

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    val nameTextView = view.findViewById<TextView>(R.id.nameTextView)
    //...
}
如果您只想完成在 Kotlin Android 扩展被弃用之前编写的教程,

findViewById 可能是目前最好的选择。

但是,使用 findViewById 可能会很乏味,而且容易出错,因为如果您正在搜索不在当前布局中的视图,它不会警告您。如果这样做,它会在运行时崩溃。为此,Google 建议使用 View Binding。开始使用视图绑定需要几个步骤,但是一旦设置好,它就是比 findViewById 更简洁的选项。官方说明are here.

最后,如果你真的不关心 Kotlin Android Extensions 被弃用并且无论如何都想使用它,它目前仍然可以正常工作,但是你必须将插件添加到你的新项目中才能启用它。 (注意这会 no longer work in Kotlin 1.8 and up。)为此,打开 app 模块的 build.gradle 文件。在 plugins 块的顶部,您可以为 kotlin-android-extensions 添加一行,如下所示:

plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'kotlin-android-extensions'
}

然后按工具栏中的“与 Gradle 个文件同步项目”按钮以启用它。

您无法直接访问视图 ID。

但是你可以使用:

  1. Jetpack 作为 Kotlin Android 扩展已弃用。来源 Kotlin Android Extensions Deprection

  2. 您可以使用视图绑定。视图绑定是一项功能,可让您更轻松地编写与视图交互的代码。在模块中启用视图绑定后,它会为该模块中存在的每个 XML 布局文件生成一个绑定 class。 资料来源:View Binding