Kotlin is officially a first-level language supported by Google. The new Beta version of Android Studio3.0 has original Kotlin support. Yesterday’s news said god J has joined Google’s Kotlin group. I think Kotlin is going to be a big deal.

kotlin.jpg

LiveData is a data holder class that holds a value and allows observation of that value. It can also be bound to Lifecycle, synchronizing with the Lifecycle of the observer. Simply put, put the data into LiveData, and then set up a listener for LiveData. When the data changes, the listener will be called automatically. Lifecycle binding will not trigger listening when an Activity is recycled. With the singleton mode, it is easy to modify data in one place and receive notifications for multiple activities and fragments.

DataBinding can make your UI code pretty clean. It takes the page logic out of your code. Make your code more focused on other things.

We set DataBinding’s ViewModel to LiveData and invoke DataBinding’s refresh in LiveData’s listener. This modifies the ViewModel anywhere, and the UI updates automatically.

Now, here’s an example. We enter text in the input box above. The text box below reflects the input in real time.

tt2.gif

AndroidStudio3.0 Beta1 Project gradle is as follows:

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    ext.kotlin_version = '1.1.3-2'
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com. Android. Tools. Build: gradle: 3.0.0 - walk'
        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
    }
}

ext.arch_version = "1.0.0 - alpha7"

allprojects {
    repositories {
        google()
        jcenter()
        mavenCentral()
        maven { url 'https://maven.google.com' }
    }
}

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

Module gradle is as follows:

apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 26
    buildToolsVersion "26.0.1"
    defaultConfig {
        applicationId "com.greendami.gdm"
        minSdkVersion 15
        targetSdkVersion 26
        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
    }
}

dependencies {
    kapt 'com. Android. Databinding: the compiler: 3.0.0 - walk'
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    implementation 'com. Android. Support: appcompat - v7:26.0.1'
    implementation 'com. Android. Support. The constraint, the constraint - layout: 1.0.2'
    testImplementation 'junit: junit: 4.12'
    androidTestImplementation 'com. Android. Support. Test: runner: 0.5'
    androidTestImplementation 'com. Android. Support. Test. Espresso: espresso - core: 2.2.2'

    compile "android.arch.persistence.room:runtime:$arch_version"
    compile "android.arch.lifecycle:runtime:$arch_version"
    compile "android.arch.lifecycle:extensions:$arch_version"

    annotationProcessor "android.arch.persistence.room:compiler:$arch_version"
    annotationProcessor "android.arch.lifecycle:compiler:$arch_version"

}

kapt {
    generateStubs = true
}Copy the code

The important thing is dataBinding {enabled = true} to enable databing.

So let’s start coding. The first is the ViewModel class, which is also a LiveData class.

package com.greendami.gdm

import android.arch.lifecycle.MutableLiveData
import android.arch.lifecycle.ViewModel

/**
 * Created by GreendaMi on 2017/8/10.
 */
class SearchViewModel : ViewModel() {
     val show_string = MutableLiveData<String>()
     val input_string = MutableLiveData<String>()
}Copy the code

There are only two fields in this class, corresponding to the content of the input box on the interface, and the display content of the text box. Next is the layout file acticity_main.xml

<?xml version="1.0" encoding="utf-8"? >
<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>
        <import type="com.greendami.gdm.SearchViewModel" />
        <variable
            name="model"
            type="SearchViewModel" />
    </data>

    <android.support.constraint.ConstraintLayout

        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.greendami.gdm.MainActivity">
        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/input"
            android:inputType="textNoSuggestions"
            android:imeOptions="actionSearch"
            tools:text="google"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{model.show_string.value}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </android.support.constraint.ConstraintLayout>
</layout>Copy the code

The top layer of the layout is the layout, and then the first one below is the data field, which is where the data is declared. The back is the normal layout. We start by declaring an object model of type SearchViewMode. Android :text=”@{model.show_string.value}” The dot value here is how LiveData is evaluated.

And then the MainActivity. Kt

package com.greendami.gdm import android.arch.lifecycle.LifecycleActivity import android.arch.lifecycle.Observer import android.databinding.DataBindingUtil import android.os.Bundle import android.text.Editable import android.text.TextWatcher import android.util.Log import com.greendami.gdm.databinding.ActivityMainBinding class MainActivity : LifecycleActivity() { var searchViewModel: SearchViewModel = SearchViewModel() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) var binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main) searchViewModel.show_string.value = "Waiting for input" binding. Model = searchViewModel binding.input.addTextChangedListener(object : TextWatcher { override fun afterTextChanged(p0: Editable?) { binding.model? .show_string? .value = p0.toString() } override fun beforeTextChanged(p0: CharSequence? , p1: Int, p2: Int, p3: Int) { } override fun onTextChanged(p0: CharSequence? , p1: Int, p2: Int, p3: Int) { } }) binding.model? .show_string? .observe( this@MainActivity, Observer{ Log.e("TAG",binding.model? .show_string? .value) Log.e("TAG",binding.hasPendingBindings().toString()) binding.invalidateAll() }) } }Copy the code

Explain the var binding = DataBindingUtil. The setContentView (this, R.l ayout. Activity_main) the load in layout, Note here that the ActivityMainBinding class may not be generated at first. Try rebuilding or restart the IDE. Once you get the Binding object, you can bind the ViewModel to the object, which is the searchViewModel in the code.

We use a Binding object. Control ID to get the control object. Such as:

binding.input.addTextChangedListener(object : TextWatcher { override fun afterTextChanged(p0: Editable?) { binding.model? .show_string? .value = p0.toString() } override fun beforeTextChanged(p0: CharSequence? , p1: Int, p2: Int, p3: Int) { } override fun onTextChanged(p0: CharSequence? , p1: Int, p2: Int, p3: Int) { } })Copy the code

Modify the value of LiveData in the listener. Because we set the LiveData observer

binding.model? .show_string? .observe( this@MainActivity, Observer{ Log.e("TAG",binding.model? .show_string? .value) Log.e("TAG",binding.hasPendingBindings().toString())
            binding.invalidateAll()
        })Copy the code

This is called when the data is modified. The first parameter here, this, is LifecycleActivity, so this listener is tied to the lifecycle of the MainActvity. Here using the binding. InvalidateAll (), and not to use the binding. ExecutePendingBindings () because it changes LiveData value, Binding. HasPendingBindings () returns false, that is to say, the databinding did not perceive the change of the data, so will not refresh interface.