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


38

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

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

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


我在describe.kotlinlang上提出类似的问题。如果有人对此主题有任何想法,请随时回复:)
xinaiz

1
看看论争科特林合成纤维一些更多的背景。
Cheticamp

Answers:


69

让我们回顾两个。


组态

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的:)


您为什么不对在中使用变量说什么呢DataBinding?我认为根本停止使用视图引用是一项重要功能。顺便说一句,您可以通过<include ... />标签“抛出”视图模型,这是另一个很大的优势。
Ircover

1
@Ircover问题是关于KAE和ViewBinding的比较。DataBinding不是该问题的一部分。
xinaiz

糟糕,抱歉)简单的误解。
Ircover

1
@BenLewis如果将绑定定义为lateinit,您仍然会遇到相同的问题。这意味着在使用代码编写片段时,不必使用任何仪表或使用KAE或ViewBinding。
Flavio

1
“应用布局更改”-使用ViewBinding时,无需构建项目,在添加具有ID的新视图之后,您可以立即执行“ binding.myTextView ..”。
Tayyab Mazhar

19

ViewBinding解决了最大的问题kotlinx.android.synthetic。在synthetic绑定中,如果将内容视图设置为布局,然后键入仅在其他布局中存在的ID,则IDE可以自动完成并添加新的import语句。除非开发人员专门检查以确保其import语句仅导入正确的视图,否则没有安全的方法来验证这不会引起运行时问题。但是在这种情况下ViewBinding,应该使用layout绑定对象访问其视图,这样就永远不会调用其他布局中的视图,并且如果要执行此操作,则会得到编译错误,而不是运行时错误。这是一个例子。

我们创建两个布局,分别称为activity_main和,activity_other如下所示:

activity_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>

activity_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>

现在,如果您这样编写活动:

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!"
    }
}

您的代码将编译而没有任何错误,但您的应用程序将在运行时崩溃。因为具有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!"
    }
}

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


1
您还可以使用LayoutInflater填充View,然后通过变量引用其定义的字段。
NapoleonTheCake

4
在现实生活中,这似乎不太可能发生。
Bencri

1
这个例子没有道理。您使用不正确。为什么要导入不正确的内容(activity_other)?您使用不正确的每个框架都可能导致问题。
Android开发人员

2

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

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

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

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

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

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

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

但是,如果您想进入部门,则可以点击下面的链接。 https://medium.com/androiddevelopers/use-view-binding-to-replace-findviewbyid-c83942471fc


2
1.始终为null安全-如果在充气之前或视图生命周期结束后使用视图绑定,则视图绑定仍然会崩溃-与合成对象没有什么不同-对于ViewBinding应使用红色。2.仅引用当前布局中的ID-是的,但是IDE指出了要从其导入给定ID的布局,因此这不是一个大问题。3.支持Kotlin和Java-错误的说法,如果可以在Android开发中使用Kotlin,那么为什么要使用Java。4.所需的代码量-Kotlin合成物的数量最少,在表中应非常低。
xinaiz

@xinaiz为什么要在充气之前使用它,请按照正确的方式使用它,否则肯定会遇到问题。你必须通过downvote前链路不见了,张贴评论 medium.com/androiddevelopers/...
SourabhTech

是的,我已经读过一段时间了。我没有在充气之前使用它,我只是说这是可能的。“正确的方法”意味着存在风险,对吗?另外,您跳过了or after view lifecycle ends一部分?
xinaiz

@xinaiz 2.但是,如果项目较大,则有可能使用错误的id;如果有多个开发人员从事项目,则有可能使用相同的资源名称。3.是的,可能有一个项目要求,您必须同时使用java和kotlin(如果项目已经在java中开发并开始使用kotlin进行集成,那么绝对有帮助)4.对于Synthetics,您必须导入单独的库,但需要进行视图绑定它已经在Gradle中存在了,所以很明显它花了更少的代码。
SourabhTech

1
回应4.什么图书馆?默认情况下启用。关于apply plugin: 'kotlin-android-extensions'vs 的争论viewBinding { enabled = true }。没有太大的区别。
xinaiz
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.