Kotlin DataBinding メモ

## Kotlinで DataBinding を実装するまえに整理してみたメモ
個人メモです。
これからDataBindingしてみようという方へ簡単なサンプルを作成しました。

## DataBinding とは
乱暴に言ってしまうと、Viewに対する操作をView上に記述できるようにする仕組み。
通常はControllerでViewを取得して、View上にオブジェクトを配置するなどの作業が必要。
これをやめてViewの中でController内のオブジェクトに相当する何かを操作して、Viewに対する処理を行う。更に言えば、View上で行なった操作結果がControllerにも返すような仕組み。双方向という場合はここまでを指す。
実例によってDataBindingの仕組みでも使ったり使わなかったりするものもあるのであとはやらかしながら確かめるしかない。。。

## プロジェクト作成
普通にAndroidStudioでプロジェクトを作成する。プロジェクト名はKotlinDataBindingSample

## build.gradle編集
add 以下を追加

```build.gradle(Module)
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
// add
apply plugin: 'kotlin-kapt'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.example.kotlindatabindingsample"
        minSdkVersion 19
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    // add
    dataBinding {
        enabled = true
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'androidx.appcompat:appcompat:1.0.2'
    implementation 'androidx.core:core-ktx:1.0.2'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:runner:1.2.0'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
```


```build.gradle(Prokect)

buildscript {
    ext.kotlin_version = '1.3.31'
    repositories {
        google()
        jcenter()
        
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.4.1'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files

        // add
        classpath 'com.android.tools.build:gradle:1.3.0-beta1'
        classpath "com.android.databinding:dataBinder:1.0-rc0"
    }
}

allprojects {
    repositories {
        google()
        jcenter()
        
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

```
一度起動してみてエラーがないことを確認

## Model作成
データを保持するクラス、、、構造体みたいなのを作成。
このモデルの内容をViewで参照できるようにする。

```User.kt
package com.example.kotlindatabindingsample.model

data class User(val name: String, val age: Int)
```

## View編集
アクティビティ内で生成したUserモデルのデータを表示できるように

``` activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools">
    <data>
        <import type="android.view.View"/>
        <variable name="user"
                type="com.example.kotlindatabindingsample.model.User"/>
    </data>
    <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            tools:context="com.example.kotlindatabindingsample.MainActivity">
        <TextView
                android:id="@+id/user_name_text_view"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="@{user.name}"
        />
        <TextView
                android:id="@+id/user_age_text_view"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="@{Integer.toString(user.age)}"
                android:visibility="@{user.age >= 18 ? View.VISIBLE : View.GONE}"
        />
    </LinearLayout>
</layout>
```
- DetaBindingするレイアウトは、`<layout></layout>`で括る。
- レイアウト内で利用する変数は、`<data> <variable ～ /> </data>`で宣言する。
- 宣言した変数の使い方は、@{user.name}のように、@{ ～ }で記述する。
- １８歳未満は表示しない`android:visibility="@{user.age >= 18 ? View.VISIBLE : View.GONE}"`などの機能を使う場合は、dataタグ内に`<import type="android.view.View"/>`を記述しておく。

## 一旦起動
この辺りで一旦起動しておく。`activity_main.xml`に対するDataBindingを中継するクラス`<パッケージ名>.ActivityMainBinding`が自動的に生成される。
このクラスはAndroidStudioからは参照できない（？）ので注意。コンパイルすれば自動的に生成されるっぽい。

## MainActivityクラスの編集

```MainActivity.kt
package com.example.kotlindatabindingsample

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.databinding.DataBindingUtil
import com.example.kotlindatabindingsample.databinding.ActivityMainBinding
import com.example.kotlindatabindingsample.model.User

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val binding: ActivityMainBinding = 
          DataBindingUtil.setContentView(this, R.layout.activity_main)

        val user = User("sample 25歳", 25)
        binding.user = user
    }
}

```
`ActivityMainBinding`クラスを使って、`activity_main.xml`へのDataBindingを宣言する。
`binding.user`に代入したオブジェクトが、Viewでは`{@user.〜}`という風に使える。
`MainActivity`クラスでは、Viewで利用したいオブジェクトを定義するだけ。
Viewを取得してViewどこかに配置する、などの処理は行わない。

## 実行結果
- 25歳の場合は、年齢まで表示

<img width="352" alt="スクリーンショット 2019-06-16 2.29.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266239/4c6bbe27-e8e3-73c5-3846-90813312f348.png">

- 14歳の場合は、18歳未満なので年齢は表示しない

<img width="352" alt="スクリーンショット 2019-06-16 2.30.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266239/115466fe-b8e8-706e-da8d-3842292e9cf9.png">

[サンプルコード](https://github.com/katafuchix/KotlinDataBindingSample)