当我在 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 properties 或 Kotlin 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。
但是你可以使用:
Jetpack 作为 Kotlin Android 扩展已弃用。来源 Kotlin Android Extensions Deprection
您可以使用视图绑定。视图绑定是一项功能,可让您更轻松地编写与视图交互的代码。在模块中启用视图绑定后,它会为该模块中存在的每个 XML 布局文件生成一个绑定 class。
资料来源:View Binding
我正在严格按照教程进行操作。我在 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 properties 或 Kotlin 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。
但是你可以使用:
Jetpack 作为 Kotlin Android 扩展已弃用。来源 Kotlin Android Extensions Deprection
您可以使用视图绑定。视图绑定是一项功能,可让您更轻松地编写与视图交互的代码。在模块中启用视图绑定后,它会为该模块中存在的每个 XML 布局文件生成一个绑定 class。 资料来源:View Binding