2022年2月2日水曜日

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

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

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


原因

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

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

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

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

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

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:tools="http://schemas.android.com/tools"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. android:orientation="vertical"
  7. tools:context=".MainActivity">
  8. <TextView
  9. android:id="@+id/textView1"
  10. android:layout_width="wrap_content"
  11. android:layout_height="wrap_content"
  12. android:text="Hello World!"/>
  13. <TextView
  14. android:id="@+id/textView2"
  15. android:layout_width="wrap_content"
  16. android:layout_height="wrap_content"
  17. android:text="Hello World!"/>
  18. :
  19. :
  20. :
  21. <TextView
  22. android:id="@+id/textView254"
  23. android:layout_width="wrap_content"
  24. android:layout_height="wrap_content"
  25. android:text="Hello World!"/>
  26. </LinearLayout>

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

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

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


対策

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

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

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

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

0 件のコメント:

コメントを投稿