Android视图对象绑定方式的抉择对比分析

前言

视图对象绑定我理解的大致分为三个时代,第一石器时代:findViewByid;第二青铜时代:Butter Knife;第三后Butter Knife时代:ViewBinding与KAE。以下是我最近看到的一篇关于视图绑定方式对比介绍的文章《谁才是ButterKnife的终结者?ViewBinding与Kotlin-android-extension的选择》,感觉不错转载如下。


Google在Android Studio 3.6 Canary 11版本中正式推出视图绑定(View Binding),相对有findViewById或者Butter Knife等现有的视图访问方式更有优势,JakeWharton也因此宣布了Butter Knife的终结:


Kotlin-android-extension

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

要找到答案就要比较一下两者的优劣,曾几何时看过一张表格,似乎ViewBinding比KAE更有优势:(Kotlin Synthetic:KAE, ???:ViewBinding)

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

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

例如有两个layout :activity_main 与 activity_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为前提

 

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的现状),所以你心中的是否已经有答案了呢?

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值