具有合成视图的ViewBinding vs Kotlin Android扩展

Rin*_*nav 9 android kotlin kotlin-android-extensions android-viewbinding

新的ViewBinding与带有合成视图绑定的Kotlin Android扩展相比如何?

除了新ViewBindings提供的NullSafety和TypeSafety之外,我们为什么还要考虑放弃在Views上使用合成绑定的Kotlin方法。

由于新的ViewBinding事先生成了Binding类,因此它的性能更高吗?

Squ*_*uti 45

ViewBinding解决了最大的问题kotlinx.android.synthetic。在synthetic绑定中,如果您将内容视图设置为布局,然后键入仅存在于不同布局中的 id,IDE 将允许您自动完成并添加新的导入语句。除非开发人员专门检查以确保他们的导入语句只导入正确的视图,否则没有安全的方法来验证这不会导致运行时问题。但是在ViewBinding你应该使用你的layout绑定对象来访问它的视图,这样你就永远不会调用不同布局中的视图,如果你想这样做,你会得到一个编译错误而不是运行时错误。这是一个例子。

我们创建了两个布局,称为activity_mainactivity_other像这样:

活动_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

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

</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)

活动_other.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:tools="http://schemas.android.com/tools"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                >

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

</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)

现在,如果你这样写你的活动:

import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_other.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        //Application will crash because "message_other" doesn't exist in "activity_main"
        message_other.text = "Hello!"
    }
}
Run Code Online (Sandbox Code Playgroud)

您的代码将编译而不会出现任何错误,但您的应用程序将在运行时崩溃。因为message_otherid的视图不存在activity_main并且编译器没有检查这个。但是如果你ViewBinding像这样使用:

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        //This code will never compile and the IDE shows you an error
        binding.message_other.text = "Hello!"
    }
}
Run Code Online (Sandbox Code Playgroud)

您的代码永远不会编译并Android Studio在最后一行显示错误。

  • 这在现实生活中似乎不太可能发生。 (20认同)
  • 这个例子没有意义。你用错了。为什么你会导入不正确的东西(activity_other)?不正确使用的每个框架都可能导致问题。 (9认同)

Sou*_*ech 11

kotlinx.android.synthetic 不再是推荐的做法,谷歌在一个提交消息中说“Reddit 线程之一

https://android-review.googlesource.com/c/platform/frameworks/support/+/882241 "

Synthetics不是由 google 开发的,它是 JetBrains 制作的 kotlin android 扩展的一部分,逐渐 google android 开发人员开始在他们的演示和源代码中用 ViewBindins 替换 Synthetics。

“现在问题来了,我们必须考虑哪一个。”

根据谷歌(视图绑定、ButterKnife、Kotlin 合成),这些库被许多应用程序成功使用并解决了同样的问题。

但是对于大多数应用,谷歌建议尝试使用视图绑定而不是这些库,因为视图绑定提供了更安全、更简洁的视图查找。

附上参考图像以快速清除事物。 在此处输入图片说明

但是,如果您想进入部门,可以按照下面给出的链接进行操作。 https://medium.com/androiddevelopers/use-view-binding-to-replace-findviewbyid-c83942471fc

  • 1. 始终空安全 - 如果在膨胀之前或视图生命周期结束之后使用,视图绑定仍然会崩溃 - 与合成没有什么不同 - 对于 ViewBinding 应该是红色的。2. 仅引用当前布局中的 id - 确实如此,但 IDE 会指出您要从哪个布局导入给定 id,因此这不是一个大问题。3. 支持 Kotlin 和 Java - 不好的论点,如果你可以在 android 开发中使用 Kotlin 那么为什么要使用 Java。4. 所需的代码量 - Kotlin 合成的数量最低,在表中应该非常低。 (14认同)
  • 回应4.什么图书馆?默认情况下它是启用的。这是关于“应用插件:'kotlin-android-extensions'”与“viewBinding {enabled = true}”的争论。差别不大。 (4认同)
  • 是的,我前段时间读过。充气之前我没有使用它,我只是说这是可能的。“正确的方式”就意味着有风险,对吗?另外,您跳过了“或视图生命周期结束后”部分? (3认同)

Hen*_*ing 10

Kotlin Android 扩展将在 Kotlin 1.4.20 中弃用,因此我建议使用 ViewBinding。

https://proandroiddev.com/migrating-the-deprecated-kotlin-android-extensions-compiler-plugin-to-viewbinding-d234c691dec7

  • 这是我们应该使用viewBinding的最合理的理由。哈哈 (5认同)

xin*_*aiz 9

让我们回顾两个。


组态

Kotlin Android扩展

  1. 导入适当的布局合成扩展名: import kotlinx.android.synthetic.main.<layout>.*
  2. 通过ID引用代码中的视图textView.text = "Hello, world!"。这些扩展的工作:ActivitiesFragmentsViews

视图绑定

  1. 在类中创建绑定引用: private lateinit var binding YourClassBinding
  2. 虚增您结合binding = YourClassBinding.inflate(layoutInflater)内部ActivityonCreate和呼叫setContentView(binding.root),或夸大它FragmentonCreateView,然后返回它:return binding.root
  3. 通过使用其ID进行绑定的代码引用视图 binding.textView.text = "Hello, world!"

类型安全

根据定义,Kotlin Android扩展ViewBinding是类型安全的,因为已将引用的视图强制转换为适当的类型。


空安全

Kotlin Android扩展ViewBinding都是null安全的。ViewBinding在这里没有任何优势。对于KAE,如果视图仅在某些布局配置中存在,IDE会为您指出:

在此处输入图片说明

因此,您只需将其与Kotlin中的其他任何可为null的类型一样对待,错误就会消失:

在此处输入图片说明


应用布局更改

如果是Kotlin Android扩展,布局更改会立即转换为合成扩展的生成,因此您可以立即使用它们。如果使用ViewBinding,则必须构建您的项目


布局使用不正确

如果是Kotlin Android扩展程序,则可能会导入不正确的布局合成扩展程序,从而导致NullPointerException。这同样适用于ViewBinding,因为我们可以导入错误的Binding类。虽然,比不正确的类名更容易忽略不正确的导入,尤其是在布局文件以Activity/ Fragment/ 命名之后View,因此ViewBinding在这里占了上风。


KAE与ViewBinding的摘要

  • 输入安全 -抽奖。
  • 空安全 -抽奖。
  • 样板代码 - KAE胜。从Kotlin Android扩展文档

Kotlin Android扩展插件使我们能够获得与其中某些库相同的体验,而无需添加任何额外的代码。

  • 应用布局的变化 - KAE获胜。与ViewBinding相比,更改是即时的。
  • 不正确使用的布局 - ViewBinding

我认为将ViewBinding替换为KAE有很大的误解。人们会听到较大的关键字,并在没有事先验证的情况下重复它们。可以肯定的是,ViewBinding现在是Java开发的最佳选择(替换ButterKnife),但是在Kotlin中与KAE相比没有优势或几乎没有优势(请参阅不正确的布局用法部分)。

旁注: 我确定DataBinding的人会喜欢ViewBinding的:)

  • @Ircover 这个问题是关于 KAE 和 ViewBinding 的比较。数据绑定不是该问题的一部分。 (4认同)
  • @BenLewis如果你的绑定定义为lateinit你仍然有同样的问题。这意味着无论您使用什么 KAE 或 ViewBinding,在片段中编写代码时都必须遵循一些严格的规则。 (3认同)
  • “应用布局更改” - 使用 ViewBinding 时,您不必构建项目,在添加带有 id 的新视图后,您可以立即执行“binding.myTextView..”。 (3认同)
  • ViewBinding 在 null 安全性方面绝对具有优势。以Fragment生命周期为例:在创建父布局之前,您可以在onCreateView中引用KAE中的视图。这在编译时不会被检测到,但会在运行时抛出 NPE。使用 ViewBinding 在引用其子布局之前,您必须先引用父布局 (2认同)