谁才是ButterKnife的终结者?ViewBinding与Kotlin-android-extension的选择

谁才是ButterKnife的终结者?ViewBinding与Kotlin-android-extension的选择_第1张图片
Google在Android Studio 3.6 Canary 11版本中正式推出视图绑定(View Binding),相对有findViewById或者Butter Knife等现有的视图访问方式更有优势,JakeWharton也因此宣布了Butter Knife的终结。
谁才是ButterKnife的终结者?ViewBinding与Kotlin-android-extension的选择_第2张图片

Kotlin-android-extension


使用Kotlin的同学都知道Kotlin-android-extension可以方便的进行视图访问,所以Kotlin开发中很少使用Butter knife。ViewBinding难道比KAE还强大吗,ViewBinding与KAE谁才能扛起Butter Knife后时代的大旗呢?

要找到答案就要比较一下两者的优劣,曾几何时看过一张表格,似乎ViewBinding比KAE更有优势:(Kotlin Synthetic:KAE, ???:ViewBinding)
谁才是ButterKnife的终结者?ViewBinding与Kotlin-android-extension的选择_第3张图片

KAE是基于Kotlin Compiler Plugin + Intellij Idea Plugin实现的,IDEA Plugin让我们可以在编辑器中使用语法糖进行试图访问,Compiler Plugin可以在编译期对语法糖脱糖。整个过程是一个编译期的的闭环,何来的编译安全问题呢?

我们知道KAE可以将layout文件中的id映射为View对象直接在Activity或Fragment中使用,但是无法保证layout是Activity/Fragment的当前视图

例如有两个layout :activity_mainactivity_other

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

我们实现Activity如下:

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

KAE会扫描res下所有layout中的id,作为代码自动补全的候选项,message_other的使用虽然可以通过编译,但是因为不是当前layout中的id,所以运行时会出错。

同样的例子如果使用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!"
    }
}

上面表格中KAE编译安全的✘也正是指的这个问题。

Null safety


还有另一张表格也做了两者的对比,当然也是以突出ViewBinding为前提
谁才是ButterKnife的终结者?ViewBinding与Kotlin-android-extension的选择_第4张图片
Only reference ids from current layout 在上面的例子已经介绍过了。Alway null-safe该如何理解呢?

先看下ViewBinding的Null-safe

Null-safe for layouts defined in multiple configurations. View binding will detect if a view is only present in some configurations and create a @Nullable property.

当有多个configuration时,需要对应多个layout,此时可能出现为空的情况,ViewBinding会在编译期发现并添加@Nullable注解。

经过实测,KAE也可以做到这一点,当某个configuration的layout缺少时,KAE同样会给出提示:
在这里插入图片描述
需要进行可空处理:
在这里插入图片描述

所以在空安全方面,ViewBinding并不比KAE有优势

How to choose?


啰嗦了这么多,到底应该如何选择呢?

首先客观的说ViewBinding比KAE的优势并不明显,都兼具了类型安全、空安全
编译速度等方面的优势(编译速度可能KAE更加,KotlinCompilerPlugin由于GradlePlugin),虽然KAE在编译安全上有缺陷,但只要开发时稍加注意也不是大问题,而且KAE的模板代码比起ViewBinding更少,从简洁性上说要更优秀,所以个人认为在Kotlin开发中,KAE与ViewBinding是不分伯仲的。

但是ViewBinding有一个优势KAE无法比拟,就是身份问题:

KAE来自JetBrains而非Google官方的,随着ViewBinding的诞生,相信Google会在未来的AOSP以及Jetpack中更多地推荐使用ViewBinding,例如下面某个commit的comment中已经可以看出端倪

kotlinx.android.synthetic is no longer a recommended practice
https://android-review.googlesource.com/c/platform/frameworks/support/+/882241

虽然JetBrains对于KAE来说已经是一种背书了,但是在Android世界中毕竟Google才是老大(参考Anko与Jetpack-KTX的现状),所以你心中的是否已经有答案了呢?

你可能感兴趣的:(Kotlin,Android)