Blog

Kotlin Android Extensions(views)はやめてViewBindingを使おう

Kotlin Android Extensionは現在2つ機能があり、findViewByIdを省略できる views とParcelableの実装を楽にしてくれる parcelize があります。

特に views は非常に便利で、僕自身もよく使っていました。(今後、Kotlin Android Extensionsと書いた場合はviewsの方を示します)

一方、ViewBindingというものも登場し、DataBindingの軽量版みたいな立ち位置で、こちらもfindViewByIdを省略することができます。

Kotlin Android ExtensionとViewBinding、DataBindingを比較し、使い分けについて議論したいと思います。

-2020/12/08追記-

kotlin 1.4.20からandroid-kotlin-extensionsはdeprecatedになりました。

2021年9月中またはそれ以降に削除される予定のため、ViewBindingへの移行が必要です。

Android Developers Blog: The future of Kotlin Android Extensions

型安全 / null安全

ViewBinding / DataBindingは正しい型にキャストされ、null安全に取得することができます。

もし、縦と横で異なるlayoutを使っており、どちらかにしか含まれないviewの場合、そのviewは(驚くべきことに)nullableになります。

一方、Kotlin Android Extensionsは型は正しい型にcastしてくれますが、常にnullableです。

パフォーマンス

findViewByIdは子viewを順番に探索していくため、複雑なlayoutで何度も呼び出すとパフォーマンスが下がっていきます。

Kotlin Android Extensionsをactivity / fragmentで使う場合は、一度findViewByIdした要素に関してはキャッシングしてくれるのですが、custom viewやview holder等で使う場合はキャッシュ機構の実装がなく、毎回findViewByIdが実行されているようです。

一方、ViewBinding / DataBindingはキャッシュが常に効くので、多くの場合に置いてパフォーマンスが向上すると考えて良さそうです。

ネストされたViewに対する動作

例えば、以下のようなlayoutを用意し、

<?xml version="1.0" encoding="utf-8"?>
<!-- layout/layout_button.xml -->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="button" />

</FrameLayout>

このように、一つのレイアウトで複数回includeしたとします。

<?xml version="1.0" encoding="utf-8"?>
<!-- layout/activity_main.mxl -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <include
        android:id="@+id/include1"
        layout="@layout/layout_button" />

    <include
        android:id="@+id/include2"
        layout="@layout/layout_button" />
</LinearLayout>

このようなケースでは、Kotlin Android Extensionsでは2つのbuttonを区別することができません。

一方、DataBinding / ViewBindingでは以下のようにアクセスすることができます。

val button1 = binding.include1.button
val button2 = binding.include2.button

Javaからの利用

Kotlin Android Extensionsは名前にkotlinとある通り、javaからは利用ができません。

ViewBinding / DataBindingはjavaからでも問題なく使えるようになっています。

ViewBindingとDataBindingの違い

Kotlin Android ExtensionsとViewBinding / DataBindingの違いを触れてきたので、ViewBindingとDataBindingの違いに関しても簡潔に述べます。

ViewBindingは、DataBindingよりシンプルに設計されており、DataBindingと比較して、以下のような機能がありません。

  • レイアウト変数、レイアウト式に対応していない(xml上にコードは書けない)
  • binding adapters等も呼び出せない

その代わり、以下のような利点があります。

  • 既存のlayoutをそのまま使える
  • コンパイルが高速

まとめ

基本的に、ViewBindingの登場によってKotlin Android Extensionsの役割は終えたと考えて良さそうです。

DataBindingの機能を使いたい場合はDataBindingを、それ以外の場合はViewBindingを使うことになりそうです。

人気の記事

kotlin coroutinesのFlow, SharedFlow, StateFlowを整理する

Jetpack ComposeとKotlin Coroutinesを連携させる

Layout Composableを使って複雑なレイアウトを組む【Jetpack Compose】

テスト用Dispatcherの使い分け【Kotlin Coroutines】

Flow.combineの内部実装がすごい話

Jetpack ComposeのRippleエフェクトを深堀り、カスタマイズも