BindingAdapterが重複作成される警告
BindingAdapterはCompanionオブジェクトに書いてはいけない
Created at

640 Words
⚠️

参考

今回の内容は全部ここに書いてあることです。

Defining Android Binding Adapter in Kotlin | by Herman Cheung | Medium


問題

ビルドログを眺めているとこんな警告が大量に発生していた。

w: warning: Binding adapter AK(androidx.recyclerview.widget.RecyclerView, com.suihan74.example.Hoge) already exists for bindItems! Overriding com.suihan74.example.Hoge.Companion#bindItems with com.suihan74.example.Hoge#bindItems

ちなみに警告は出るがビルドは成功する。

原因

原因は、companion objectの中にBindingAdapterを記述していたこと。
kotlinのcompanion objectは静的なフィールドやメソッドを定義するために有用だが、Javaコードに展開されると次のような状態になる。

kotlin

package com.suihan74.example

class Hoge {
    companion object {
        @JvmStatic
        @BindingAdapter("items")
        fun bindItems(view: RecyclerView, items: List<Item>?) {
            // 省略
        }
    }
}

Java

package com.suihan74.example;

public final class Hoge {
    public static final class Companion {
        static void bindItems(RecyclerView view, List<Item> items) {
            // 省略
        }
    }
    public static bindItems(RecyclerView view, List<item> items) {
        Companion.bindItems(view, items);
    }
}

Hoge.bindItems()でもhoge.Companion.bindItems()でもアクセスできるようにふたつの静的メソッドが作成されるようだ。
最初の警告文通り、これでは同じパラメータのためのBindingAdapterが重複してしまう。

解決法

companion objectを使わないで普通に書く。奇を衒わない。素直に公式で紹介されてるものを踏襲する。

拡張関数として用意する

@BindingAdapter("items")
fun RecyclerView.setItems(items: List<Item>?) {
    // 省略
}

簡単でいいと思う。
やたら拡張関数生やすのはちょっとと思ったら次の方法。

シングルトンオブジェクトに書く

object RecyclerViewBindingAdapters {
    @JvmStatic
    @BindingAdapter("items")
    fun setItems(view: RecyclerView, items: List<Item>?) {
        // 省略
    }
}

内部クラスとして適当なクラス内に書いてもいいので、たとえばRecyclerViewなら各モデル用のListAdapterを必ず書いているはずなので、そこに書くとかするとまとまりがあってよろしい感じがする。

See Also