LoginSignup
0
1

More than 3 years have passed since last update.

Sunflowerリポジトリで学ぶJetPack〜DataBinding編

Last updated at Posted at 2020-07-26

新型コロナの影響で自宅待機になってしまい、その間勉強するものとしてSunflowerリポジトリを
勧めてもらいました。

JetPackのライブラリのうち、今回はDataBinding編です

尚、引用しているソースは明記しているところ以外は、全てSunflowerのリポジトリのものです。 

環境

  • 確認時はAndroid Studioのバージョンは 3.6.2を使用
  • Data bindingはサポートライブラリなので、Android 4.0(API レベル 14)以降で利用可能
  • Android Plugin for Gradle1.5.0以降でサポートされているが、なるべく最新を使用したほうがいい(らしい)

DataBinding を利用するのに必要なこと

  • ビルド環境設定
  • レイアウトファイルを変更
  • 購読処理の実施(LiveDataとの連携)

準備

Build.gradleファイルでData Bindingの機能を有効にします
Sunflowerではapp/build.gradleに記載してありますねー!(^^)

app/build.gradle

android {
    compileSdkVersion rootProject.compileSdkVersion
    dataBinding {
        enabled = true
    }

レイアウトファイル

ここではData Bindingを利用しているfragment_garden.xmlを見てみましょう

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>

ポイント

  1. レイアウトファイルが<Layout>タグで開始されている。(<LinearLayout>とかじゃない)
  2. その中に<data>タグがある。
  3. さらにその中に<variable>タグでバインディング変数を定義している
  4. バインディング変数はnameで名前を、typeで型を定義している
  5. バインディング変数の利用箇所は@{変数名}と記載する ここでは、"@{hasPlantings}"と記載している *ちなみに"@{viewModel.imageUrl}"のようなプロパティ参照もできる(list_item_garden_planting.xml参照)

ここではhasPlantingsの値によってRecyclerViewとなにもない時に表示するLinearLayoutを出し分けてますね

データのバインド

ではレイアウトファイルで記載した変数をどう関連付けるのか、Kotlinファイルを確認してみましょう

GardenFragment.kt
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. FragmentListViewRecyclerViewなどいずれかのアダプター内でデータバインディングの変数を利用する場合は、DataBindingUtil#inflate()メソッドも利用可能です

DataBindingUtil#inflate()利用箇所

GardenPlantingAdapterでは、DataBindingUtil#inflate()メソッドを利用してバインディングしていました。

GardenPlantingAdapter.kt
    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との連携)

それでは、購読する処理を見てみましょう

GardenFragment.kt
    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を直接購読しているのではなく、その情報を算出するためのplantAndGardenPlantingsobserveしているんですね!
こうすることで、plantAndGardenPlantingsの値が変更された時にresultが更新されて、そこから算出された
hasPlantingsRecyclerViewを更新すると。

ここから先はLiveData編に記載します!

参考サイト

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1