今更遅れてDataBinding事始め(3.5)
後で加筆予定
- 前回のお話
- エントリ内容のキッカケ
- AS 2.2.2 にして困っていること
- 何がマズイのか
- tools属性の利用について
- data-bindingのクラス名の変更について
- bindする式記述に関して
- 関数のbindingに関して
前回のお話
- 今更遅れてDataBinding事始め(1) - exception think
- 今更遅れてDataBinding事始め(2) - exception think
- 今更遅れてDataBinding事始め(3) - exception think
エントリ内容のキッカケ
一応双方向の話とかはローカルで試しているんですが、イマイチしっくり来ないので
それ以前の使い勝手的なところに関してメモしておこうかと
AS 2.2.2 にして困っていること
- data-binding用のlayoutにすると高確率でlayout editorのプレビューでエラーが出る
- 酷いときにはrendering timeout というExceptionが発生*1
何がマズイのか
通常状態の最近の layoutプレビュー
<application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" /> //★ココ
で、テンプレートのレイアウトが作成される時
- app/activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" tools:content=".MainActivity" />//★ココ </android.support.v4.widget.DrawerLayout>
の tools:content を指定しないと、themeを探してくれなくなったわけで
一時期 target-sdk を下げればという話もあったけど
状況のようで、使いづらくなったな~というのが感想。
data-bindingでの layoutプレビュー
で、上記の app/activity_main.xml を下記のように修正すると、プレビューが失敗しやすくなる
これってbinding情報を除いた変換済みのxmlを参照しているわけじゃないからだろうなーというのが推察される動作。
現在のレイアウトを解析してプレビュー作ろうとして失敗してるんじゃないだろうか?
- かなりNGなパターン
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"> <android.support.v4.widget.DrawerLayout tools:content=".MainActivity" />//★ココ </android.support.v4.widget.DrawerLayout> </layout>
- 比較的レンダリングエラーが少ないパターン
<?xml version="1.0" encoding="utf-8"?> <layout> <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" tools:content=".MainActivity" />//★ココ </android.support.v4.widget.DrawerLayout> </layout>
これ今後に期待系なのでしょうかね。。
ちなみにfragmentに関しても
AS 2.2.2でレイアウトプレビュー時のlintチェックが厳しくなったようで、theme参照エラーが出るわけですが
StackOverFlowに載ってる tools:content指定だと解決しないんですよね・・*3
<fragment android:id="@+id/map" class="com.google.android.gms.maps.SupportMapFragment" android:layout_width="match_parent" android:layout_height="match_parent" tools:content=".MainActivity" />//★ココ
tools:layoutを指定しろ
って奴らしいんですけど、そんなのカスタムFragmentでない限り解らんわ~
と言いたい。
他者ライブラリとか入れた場合はどうなの?
カスタムattitudeがあるサードパーティーUI libraryで
attitude参照エラーが出まくりでポイズン。
aar形式で同梱されてるはずなんですけどね~(^^;) 正直訳わからない。
yahooの人が、極力標準library使うのが安心
とかいう話聞くのよくわかるわ~
tools属性の利用について
らへんの話の他に
data-bindingを使うと
- android:text 辺りの箇所が全部潰れるわけです。
これだと AS 2.2 新機能とか言われている layout画面保存機能とか意味なくない?
の状態なので、下記のattribute が追加されています
- Designtime Layout Attributes
というのが追加されている状態です
<TextView android:text="Name:" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <EditText tools:text="John Doe" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ImageView tools:src="@drawable/bird" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:visibility="gone" tools:visibility="visible"/> <android.support.v7.widget.RecyclerView android:id="@+id/list" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginLeft="16dp" android:layout_marginRight="16dp" app:layoutManager="LinearLayoutManager" tools:listitem="@layout/fragment_book_list_item" /> <!--G様が用意しているlistitem定義--> tools:listitem="@android:layout/simple_list_item_2" tools:listheader tools:listfooter. は RecyclerView には元々対応プロパティが存在しないので意味がない (ListViewには存在するが・・)
まあ気休め程度なのかな・・。
- あんまり意味があると思えない属性
<!-- includeタグで呼ばれるレイアウトの方で、親レイアウトを指定 --> tools:showIn="@layout/activity_main" tools:layout_height="match_parent" tools:targetApi="M" tools:locale="es" tools:background ・・背景変更だけど、これあんまり使わない気がする・・
因みに、勿論Data-bindingを書いているレイアウトだと
tools:XXXを書き換える度にビルドが走るわけで
瞬間的にカクカクしますね・・*4
appcompatとかsupport-library系の表示チェックが
未だに実機で動かさないとわからないのは正直死んでると思うんですけどね。。(汗
data-bindingのクラス名の変更について
これ現在動きません。コマンドラインでは動くようなのですが
補完関係が全滅・・ たぶんlayoutのファイル名でindex作っちゃってるからだろうな。。という感じ
パーサーとかのチェックではなく、高速化のためにテキストベースでチェックなんだろうな・・というのが感想
<data class="MainActivityViewHolder"> ... </data>
因みに前動いていたらしい、下記の記述はコマンドラインでもだめ・・・
<data class="MainActivityViewHolder"/>
bindする式記述に関して
触ってみたところ、下記の記述あたりはNGでした
NGなパターン
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text='@{String.format("%.1f", user.money)}'/>
OKなパターン(AS.2.2.2ではNGになった)
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{String.format('%.1f', user.money)}"/>
まあ
- activity_main.xml
<TextView android:id="@+id/text_view2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{person.getName() + ` (` + person.getAge() + `)`}"/>
と記載すると
- ActivityMainBinding.java
String name = person.getName(); int age = person.getAge(); textView2.setText(name + " (" + age + ")");
と展開される仕様のようなのでそういう物なんでしょうね。。*6
AS2.2.2で完全OKなパターン
上記の設定ですが、現在は動かないようです。AS 2.2.1 までは動いていたようなのですが。。
- [`]が変換式の中に入っていると、一律変換前 lintチェックでエラー
対処法として下記が現在は正解のようです。
<string name="money_str">%.1f</string> <string name="age_str">%s(%s)</string>
- layout.xml
android:text="@{ @string/money_str(user.money) }"/> android:text="@{ @string/age_str(person.getName(),person.getAge()) }"/>
公式のサイトだと、どれでも書ける風な記述が有るのですが・・・(汗
関数のbindingに関して
- app/activity_main.xml
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="@{activity.onClick}"/>
って書き方が例題によく載ってますが、これって
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="onClick"/>
な書き方が元からできますし、Cmd+Bで呼べるのは下の方なんで
この書き方できて何が嬉しいの? というお話になるわけですけど。
まあ onClickの実装コードを見たことが有りますが、
- Contextの参照をActivityの時のみマッピングする
- 参照Contextを instance of Activity でわざわざ判定している
- その為、FragmentのGUI部品のところで onClickListenrを実装せよ みたいな糞実装がまかり通る。。
- したがってFragmentで android:onClick を実行できない
- 何のためのFragmentか!*7
- ActivityをFatにしないためのやつじゃないの?
で、data-bindingでFragment上の関数を呼べるかどうか? で試してみました
結論としては
- activityの参照は一律OK
- fragmentの参照ができるものとできないものが有る
- 参照不可=>生成エラーにして弾いているような挙動?
- variable でFragmentは指定できません的なエラーが出る
<data> <variable name="activity" type="hoge.fuga.mainActivity"/> <variable name="fragment" type="hoge.fuga.hogeFragment"/> </data> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="@{fragment.onHogeClick}"/>
OKなパターン
- DataBindingUtil.setContentView;
- activityでの例で書かれているやつ
- XXXBinding.bind(view);
- fragmentでの例で書かれているやつ
- DataBindingUtil.setContentView;
NGなパターン
- DataBindingUtil.inflate
- DataBindingUtil.getBinding
- adapterとかカスタムViewとか