3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2017-07-01

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'

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

3
2
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
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?