2022年2月2日水曜日

ViewBindingで配置できるViewの上限は253個まで

 ViewBindingを使ってAndroid開発をしているとき、

大量にViewを作るとBindingでエラーなることがあった。


原因

エラー文も文字化けてるし、原因を調べていくと

Javaの言語仕様「メソッドの引数の数の上限は254個」というものに引っかかっていた。

ViewBindingで自動生成されるコードを読んでいくと、

コンストラクタの第一引数がrootのView(一番外側のLayout)で、残りはlayout上で定義したView達が一つずつ渡されていた。

つまり、以下のようにTextViewを254個並べるレイアウトを用意すると

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    tools:context=".MainActivity">
    
    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"/>
    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"/>
        
        :
        :
        :
        
    <TextView
        android:id="@+id/textView254"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"/>
</LinearLayout>

以下のような、超巨大コンストラクタが自動生成される。
※引数の順番は適当になっている模様。
private ActivityMainBinding(@NonNull LinearLayout rootView, @NonNull TextView textView1,
      @NonNull TextView textView10, @NonNull TextView textView100, @NonNull TextView textView101,
      @NonNull TextView textView102, @NonNull TextView textView103, @NonNull TextView textView104,
      @NonNull TextView textView93, @NonNull TextView textView94, @NonNull TextView textView95,
      :
      :
      @NonNull TextView textView96, @NonNull TextView textView97, @NonNull TextView textView98,
      @NonNull TextView textView99) {

よって、Layout内にViewが254個以上あると、自動生成されるコードのコンストラクタの引数の数が255個以上になってしまい、コンパイルエラーになる仕組。

なので、ViewBindingで扱えるViewの上限個数は253個ということになる。


対策

ViewがViewBindingの引数になる条件はViewIDを持っている事。

なので操作不要なViewにはIDを振らないようにしよう。

でもレイアウト側で相対位置調整等をしていたらViewIDを振らざる負えない...

そういう時はViewBindingを使うのをやめて、原始的にfindViewByIdを使って制御しよう。

0 件のコメント:

コメントを投稿