新型コロナの影響で自宅待機になってしまい、その間勉強するものとしてSunflower
リポジトリを
勧めてもらいました。
JetPackのライブラリのうち、今回はDataBinding
編です
尚、引用しているソースは明記しているところ以外は、全てSunflower
のリポジトリのものです。
環境
- 確認時は
Android Studio
のバージョンは3.6.2
を使用 -
Data binding
はサポートライブラリなので、Android 4.0
(API レベル 14)以降で利用可能 -
Android Plugin for Gradle
の1.5.0
以降でサポートされているが、なるべく最新を使用したほうがいい(らしい)
DataBinding を利用するのに必要なこと
- ビルド環境設定
- レイアウトファイルを変更
- 購読処理の実施(LiveDataとの連携)
準備
Build.gradle
ファイルでData Binding
の機能を有効にします
Sunflower
ではapp/build.gradle
に記載してありますねー!(^^)
android {
compileSdkVersion rootProject.compileSdkVersion
dataBinding {
enabled = true
}
レイアウトファイル
ここではData Binding
を利用しているfragment_garden.xml
を見てみましょう
<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">
<data>
<variable
name="hasPlantings"
type="boolean" />
</data>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/garden_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:layout_marginStart="@dimen/card_side_margin"
android:layout_marginEnd="@dimen/card_side_margin"
android:layout_marginTop="@dimen/margin_normal"
app:isGone="@{!hasPlantings}"
app:layoutManager="androidx.recyclerview.widget.StaggeredGridLayoutManager"
app:spanCount="@integer/grid_columns"
tools:listitem="@layout/list_item_garden_planting"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
app:isGone="@{hasPlantings}">
:
:
</LinearLayout>
</FrameLayout>
</layout>
ポイント
- レイアウトファイルが
<Layout>タグ
で開始されている。(<LinearLayout>
とかじゃない) - その中に
<data>タグ
がある。 - さらにその中に
<variable>タグ
でバインディング変数を定義している - バインディング変数は
name
で名前を、type
で型を定義している - バインディング変数の利用箇所は
@{変数名}
と記載する
ここでは、"@{hasPlantings}"
と記載している
*ちなみに"@{viewModel.imageUrl}"
のようなプロパティ参照もできる(list_item_garden_planting.xml
参照)
ここではhasPlantings
の値によってRecyclerView
となにもない時に表示するLinearLayout
を出し分けてますね
データのバインド
ではレイアウトファイルで記載した変数をどう関連付けるのか、Kotlin
ファイルを確認してみましょう
class GardenFragment : Fragment() {
private lateinit var binding: FragmentGardenBinding
:
:
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentGardenBinding.inflate(inflater, container, false)
val adapter = GardenPlantingAdapter()
binding.gardenList.adapter = adapter
binding.addPlant.setOnClickListener {
navigateToPlantListPage()
}
subscribeUi(adapter, binding)
return binding.root
}
:
:
}
ポイント
1. データバインディングを実施すると、バインディングクラスがレイアウトファイルごとに作られる。 作られるクラスの名称は下記のルールで決定されます
バインディング クラスはレイアウト ファイルごとに生成されます。
デフォルトのクラス名は、レイアウト ファイルの名前がパスカルケースに変換され、Binding サフィックスが付加されたものになります。
→ここの場合はfragment_garden.xml
のレイアウトファイルからFragmentGardenBinding
クラスが作成されます
2. データバインディングの変数を利用するために、1.
で自動生成されたバインディングクラスでinflate()
します。
3. Fragment
、ListView
、RecyclerView
などいずれかのアダプター内でデータバインディングの変数を利用する場合は、**DataBindingUtil#inflate()
**メソッドも利用可能です
DataBindingUtil#inflate()
利用箇所
GardenPlantingAdapter
では、DataBindingUtil#inflate()
メソッドを利用してバインディングしていました。
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(
DataBindingUtil.inflate(
LayoutInflater.from(parent.context),
R.layout.list_item_garden_planting, parent, false
)
)
}
購読処理の実施(LiveDataとの連携)
それでは、購読する処理を見てみましょう
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentGardenBinding.inflate(inflater, container, false)
:
:
subscribeUi(adapter, binding)
return binding.root
}
private fun subscribeUi(adapter: GardenPlantingAdapter, binding: FragmentGardenBinding) {
viewModel.plantAndGardenPlantings.observe(viewLifecycleOwner) { result ->
binding.hasPlantings = !result.isNullOrEmpty()
adapter.submitList(result)
}
名前の通りsubscribeUi()
メソッドで購読処理を実施しています。
なるほどー。 ここでは、実際にレイアウトにバインディングしたhasPlantings
を直接購読しているのではなく、その情報を算出するためのplantAndGardenPlantings
をobserve
しているんですね!
こうすることで、plantAndGardenPlantings
の値が変更された時にresultが更新されて、そこから算出された
hasPlantings
でRecyclerView
を更新すると。
ここから先はLiveData編に記載します!
参考サイト
- Sunflowerリポジトリ
- DataBinding: 公式ドキュメント
- LiveData: :公式ドキュメント