KotlinでMVVMでデータバインディングしようとした時にはまったこと

Androidアプリをkotlin+MVVMで作ろうとした時にはまったことを備忘のためにメモしておきます。
(ちなみに、Android Studioのバージョンは2.3と3.0を試しましたが、両方で再現しました)

とりあえずテスト用に、ログイン用のViewを用意してみました

#準備
##build.gradle
build.gradleファイルはこんな感じです。

```build.gradl(プロジェクト)
buildscript {
    ext.kotlin_version = '1.1.3'
    ext.android_plugin_version = '2.3.3'
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.0-alpha4'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

        classpath "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

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

```build.gradle(app)
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "testApp"
        minSdkVersion 24
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    dataBinding {
        enabled = true
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }
    sourceSets {
        main.java.srcDirs += 'src/main/kotlin'
    }

}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.3.1'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'

    testCompile 'junit:junit:4.12'

    kapt "com.android.databinding:compiler:$android_plugin_version"
    compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
}
kapt {
    generateStubs = true
}
repositories {
    mavenCentral()
}
```

##レイアウトファイル
レイアウトファイルはこんな感じです。

```login_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable name="loginUser" type="test.app.viewmodel.login.LoginUser"/>
    </data>
     <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center">

        <EditText
            android:id="@+id/editText"
            android:layout_width="240dp"
            android:layout_height="wrap_content"
            android:ems="10"
            android:inputType="textPersonName"
            android:hint="ユーザID"
            android:text="@{loginUser.userName}" />

        <EditText
            android:id="@+id/editText3"
            android:layout_width="240dp"
            android:layout_height="wrap_content"
            android:ems="10"
            android:inputType="textPassword"
            android:hint="password"
            android:text="@{loginUser.password}"/>

        <Button
            android:onClick="@{loginUser::login}"
            android:id="@+id/login"
            android:text="Login" />

    </LinearLayout>
</layout>
```

##ViewModel
ViewModel用のクラスとしてLoginUserを作成します。
まだなにも必要な処理を実装していないので極めてシンプル。

```LoginUser.kt
class LoginUser(var userName: ObservableField<String>, var password: ObservableField<String>) {

    fun login(view: View) {
    }
}
```

##Activity
Activity。こちらもシンプル。

```LoginActivity.kt
class LoginActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding = DataBindingUtil.setContentView<ActivityLoginBinding>(this, R.layout.activity_login)

        binding.loginUser = LoginUser(ObservableField(""), ObservableField(""))
    }
}
```

#動かしてみる
さあ、ビルドエラーも出ないことだし、早速動かしてみよう。
・・・が、実際に起動しようとするとエラー発生。
`java.lang.NoClassDefFoundError: Failed resolution of: Lkotlin/jvm/internal/Intrinsics;`

`LoginActivity.kt`のこの1行をコメントアウトすると、このエラーは発生しない。
`binding.loginUser = LoginUser(ObservableField(""), ObservableField(""))`
なんだこりゃ・・・？

ここでかなりハマったんですが、app用のbuild.gradleにこれを1行追加するだけで解決しました。
`apply plugin: 'kotlin-android-extensions'`

```build.gradle(app)
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
```

とりあえずこれで先に進めそう。