Android Architecture ComponentのLiveDataの使い方

#はじめに
今回はAndroid Architecture Component(以下AAC)にあるLiveDataに関する説明をしていきます。
とっても便利なものなので覚えておいて損はないです。

EditTextに入力した値をTextViewにそのまま表示させるアプリを作りながら説明していきます。


#今回説明しないこと
AACの説明
BindingAdapter等の説明
ViewModelのこと

#環境
appレベルのbuild.gradleに以下の記述をしてください。

```gradle:build.gradle
def lifecycle_version = "2.2.0"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
implementation "androidx.fragment:fragment-ktx:1.2.5"
```

#LiveDataとは
[LiveDataの概要](https://developer.android.com/topic/libraries/architecture/livedata?hl=ja)

LiveDataとは監視可能なデータホルダークラスです。
RxJavaなどでよくある監視とは違い、Androidのライフサイクルに応じた監視が可能です。

まずはサンプルを見ていきましょう。
以下のクラスとファイルを用意してください。

- MainActivity
- MainFragment
- fragment_main.xml

```kotlin:MainViewModel
class MainViewModel(application: Application) : AndroidViewModel(application) {

    val liveData: MutableLiveData<String> = MutableLiveData()
}

```

今回は簡単なサンプルなのでプロパティは1つだけです。
このMutableLiveDataというのは変更可能なLiveDataです。

これで監視可能なStringのプロパティができました。

このViewModelをActivityで生成します。

```kotlin:MainFragment
class MainFragment : Fragment() {

    private val viewModel: MainViewModel by viewModels()
    
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return super.onCreateView(inflater, container, savedInstanceState)
    }
}
```

ViewModelの生成方法に関する説明は[こちら](https://qiita.com/dosukoi_android/items/6ac109b3d00840f9f9c8)にちょっと書いてあるので参考にしてください。


#データバインディングとは
[データバンディングの概要](https://developer.android.com/topic/libraries/data-binding?hl=ja)

> データ バインディング ライブラリは、プログラムではなく宣言形式を使用して、レイアウト内の UI コンポーネントをアプリのデータソースにバインドできるサポート ライブラリです。

# アプリを作っていく

fragment_main.xmlの一番上の行で右クリックをして、Show Action Context -> Convert to dataBinding layoutをクリックすると

```xml:fragment_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>
```

こんな感じになります。

そしてFragment側でこのレイアウトを読み込むためにこんな感じにしていきます。

```kotlin:MainFragment
override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? = FragmentMainBinding.inflate(inflater, container, false).let {
        it.root
    }
```


EditTextに入力したものをそのままTextViewに表示させるためにまずはEditTextとTextViewを用意します。

```xml
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <EditText
            android:id="@+id/edit_text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintTop_toTopOf="parent"
            android:layout_margin="16dp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintTop_toBottomOf="@id/edit_text"
            android:layout_margin="16dp"/>

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

```

そしてxmlで先ほどのliveDataを使うためにViewModelを読み込みます。

dataタグの中に

```xml:fragment_main.xml
 <variable
            name="viewModel"
            type="com.example.hogehoge.MainViewModel" />
```

そしてEditTextには

```xml
<EditeText
  android:text="@={viewModel.liveData}" />

```

TextViewには

```xml

<TextView
  android:text="@{viewModel.liveData}" />
```

と加えます。

しかしこれだけではxmlにViewModelは渡せていません。Fragment側からViewModelを渡してあげないといけません。なのでこうしましょう


```kotlin:MainFragment
override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? = FragmentMainBinding.inflate(inflater, container, false).let {
        it.lifecycleOwner = viewLifecycleOwner
        it.viewModel = viewModel
        it.root
    }
```

こうすることでEditTextに入力したものがリアルタイムでTextViewに表示されるはずです。

# まとめ
Android Architecture Componentは新しいライブラリなので詳しく解説されている記事があまり多くないので、初心者向けの記事を今後も書いていきたいと思います。