Google codelabs Android DataBinding のコードのつながりをふわ~っと確認
最近、Databindingを理解するために、Google codelabs Android DataBindingで学習してみたのですが、思考停止で書かれている通りに実装したところ、Databindingは実装できたものの、どのコードと、どのコードが関連して動作しているのかが、いまいちピンときていなかったので、コード同士のつながりを確認することにしました。
この記事はその確認結果のまとめです。
Google codelabs Android DataBindingで作るもの
このCodelabsでは以下のようなものを作ります。(ほぼ完成しているものが準備されている)
LIKEボタンをポチポチするとLikesの数字が増えて、Likesが一定以上になると、プログレスバーとアイコンが変化します。
最初から準備されているコードは、DataBindingを使用せずにこの挙動を実現している状態なので、それを修正してDataBindingで実現する、というのがこのCodelabsの主旨です。
Codelabsの内容
全力でサボりますが、こちらの記事で全編内容が紹介されています。分かりにくい部分(Codelabs内のケアレスミスとか)も注釈として書かれてるので参考になりました。
コードのつながりを読み解く
読み解くというほどのものでもないかもですが、読み解きます笑
※ここで扱うコードは、Codelabsの最初に提供されるものではなく、Codelabsが完了した段階でのものです。
かなりざっくり言うと、このアプリは
・PlainOldActivity.kt
・SimpleViewModel.kt
・BindingAdapter
・plain_activity
で構成されています。
これらの中から、DataBindingの構成要素を独断と偏見で抜き出すと、こんな概略図になります。(いろいろ省略してます)
まず、plain_activity.xml内でレイアウト変数(layout variables)が定義されています。
<data>
<variable
name="viewmodel"
type="com.example.android.databinding.basicsample.data.SimpleViewModel"/>
</data>
nameはviewmodelとなっていて、
typeは"com.example.android.databinding.basicsample.data.SimpleViewModel"
を指定しており、これはSimpleViewModel.ktのことを指しています。
なので意味的には、「viewmodelは、SimpleViewModel.ktのことを指す」という具合になりそうです。
続いてタグ内で
android:text="@{}"というような表記 (layout expression、レイアウト式) が出てきます。
ここにdataタグ内で記述したレイアウト変数が入ります。
こんな感じ↓
<TextView
android:id="@+id/plain_name"
android:text="@{viewmodel.name}"
以下省略
/>
ここでdataタグ内のnameで定義した、viewmodelが@{viewmodel.name}という形で記述されています。
これはデータの紐付け先を示しています。
viewmodelはSimpleViewModel.kt(com.example.android.databinding.basicsample.data.SimpleViewModel)を型として指定していたので、「SimpleViewModel.ktからnameを引っ張って来い」というように読めます。
ただ、plain_activity.xmlからSimpleViewModel.ktへ直接紐付けされているわけでありません。
PlainOldActivity.ktは以下のようになっています。
class PlainOldActivity : AppCompatActivity() {
// Obtain ViewModel from ViewModelProviders
private val viewModel by lazy { ViewModelProviders.of(this).get(SimpleViewModel::class.java) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//➀
val binding : PlainActivityBinding =
DataBindingUtil.setContentView(this, R.layout.plain_activity)
binding.lifecycleOwner = this
//➁
binding.viewmodel = viewModel
}
}
➀はbinding先のレイアウト(plain_activity.xml)が定義されています。
➁はbinding.viewmodel = viewModelと定義されています。
binding.viewmodelの”viewmodel”は、plain_activity.xmlで定義したviewodelのことを指しています。
一方、右辺のviewModel(※Mが大文字なので”viewmodel”とは異なる)はSimpleViewModel.ktのViewModelを、 ViewModelProvidersで受け取ったものです。
なので、binding.viewmodel = viewModelは
plain_activity.xmlとSimpleViewModel.ktのViewModelの紐付けを表しています。
plain_activity.xmlとSimpleViewModel.ktが紐づけされた状態なので、
android:text="@{viewmodel.name}"や、app:hideIfZero="@{viewmodel.likes}"**のように、レイアウトからSimpleViewModel.ktの変数(name, likes)を引用することができます。
例えばnameは、_nameが代入されており、_nameはMutableLiveData("Ada")として定義されているので、Nameのところに”Ada”が表示されます。
BindingAdapter
さて、残りのBindingAdapter.ktでは、plain_activity.xmlが受け取った変数を引数とするメソッドが定義されています。以下に一例を挙げます。
@BindingAdapter("app:popularityIcon")
fun popularityIcon(view: ImageView, popularity: Popularity) {
val color = getAssociatedColor(popularity, view.context)
ImageViewCompat.setImageTintList(view, ColorStateList.valueOf(color))
view.setImageDrawable(getDrawablePopularity(popularity, view.context))
}
<ImageView
app:popularityIcon="@{viewmodel.popularity}"
以下省略
/>
この場合だと@BindingAdapter(app:popularityIcon)という表記で、popularityIconメソッドが、plain_activity.xmlのImageViewと紐付けされています。
メソッドの引数の型は、(ビューの型,レイアウト側から受けとる変数の型)となっています。
上の例だと、fun popularityIcon (view: ImageView, popularity: Popularity)のようになっていて、渡されたpopularityの中身によってメソッドの処理結果が変わるため、ImageViewの画像表示が切り替わるようになっています。
これで、SimpleViewModel.ktからBindingAdapter.ktまでのつながりが(ふわ~っと笑)確認できました。
BindingAdapterの部分だけ抜き出した場合はこんな感じ↓
ボタンタップからUI更新の流れ
このアプリはLIKEボタンがトリガーになっていて、LIKEボタンのタップ回数によって画像や色が変わっていきますが、どういう挙動になっているのか確認するために、流れをまとめました。
(図はなんやかんや省略してます。"イメージをつかむ"程度の認識で眺めてください)
LIKEボタンのタップ
・LIKEボタンを押すと、ボタンがSimpleViewModelのonLike()メソッドと紐付いているので、_likesが増える。
↓
・_likesはlikes、popularityの二つのLiveDataに代入されるので、2つに分岐する。
likes側
➀TextViewがlikesを受け取り、String型に変換し、タップ数として表示する。
➁プログレスバー(ProgressBar)は2つの@BindingAdapterと紐づいているので分岐する。
➁-1 likesが0ならばプログレスバーを非表示、それ以外の場合は表示する。
➁-2 likesの数量に応じてプログレスバーの進捗具合を表示する。
popularity側
Transformations.mapで_likesがPopularity型へ変換され、when式でPopularityレベルを分ける。
↓
➀、➁共にSimpleViewModel.ktからpopularityを受け取り、@BindingAdapterで紐づいたメソッドへ、引数として渡す。
➀はImageViewの画像の切り替え、➁はプログレスバーの色変更をする。
感想
まとめるのにだいぶ時間がかかってしまいましたが、概略図がなんとなくイメージできるようになったので、やった意味はあったと思います。実際にたくさん使って、何か作ってみようと思います~^^
Author And Source
この問題について(Google codelabs Android DataBinding のコードのつながりをふわ~っと確認), 我々は、より多くの情報をここで見つけました https://qiita.com/Bu-Kohei/items/1d27b4e1424cbbaae497著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .