为啥我在 Kotlin 中键入视图名称/ID 时会出现“未解析的引用”错误?

Posted

技术标签:

【中文标题】为啥我在 Kotlin 中键入视图名称/ID 时会出现“未解析的引用”错误?【英文标题】:Why do I get "unresolved reference" error for my view's name/ID when I type it in Kotlin?为什么我在 Kotlin 中键入视图名称/ID 时会出现“未解析的引用”错误? 【发布时间】:2021-09-15 02:21:00 【问题描述】:

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

例如,在 XML activity_main.xml中:

<TextView
    android:id="@+id/nameTextView"
    android:layout_
    android:layout_/>

在 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 Extensionssynthetic view properties kotlin-android-extensions,并且该功能已弃用

【问题讨论】:

【参考方案1】:

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

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

2017 年至 2020 年编写的教程经常使用此功能,如果没有更新,他们可能甚至不会提及它的名称,因为它被视为理所当然的包含在新项目中的插件.

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

它们污染了全局命名空间 它们不公开可空性信息 它们仅适用于 Kotlin 代码

获取视图参考的快捷方式是使用findViewById。 View 的类型应该放在括号&lt;&gt; 内。在一个 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)

在片段中,您可能正在使用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 文件同步”按钮启用它。

【讨论】:

【参考方案2】:

您不能直接访问视图 ID。

但你可以使用:

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

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

【讨论】:

以上是关于为啥我在 Kotlin 中键入视图名称/ID 时会出现“未解析的引用”错误?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在使用 kotlin 将数据添加到 firebase 实时数据库时会得到重复值?

为啥我在 Xcode 11 Beta 5 中使用 ForEach 时会出错?

为啥我在使用 POST 控制器时会丢失所有数据?

为啥人像视图照片水平显示?

为啥我在尝试快速传递 segue 上的变量时会收到这些错误?

为啥我在使用这个 UIView 动画块时会看到生涩的动画?