Kotlin是谷歌官方最新支持的一级语言,新版的Android Studio3.0 Beta 版已经原声支持Kotlin。昨天的新闻说J神也加入了谷歌的Kotlin组,以为Kotlin会成为大势啊!php
LiveData 是一个数据持有者类,它持有一个值并容许观察该值。它还能够与Lifecycle绑定,与观察者的生命周期同步。简单的说就是,把数据放到LiveData里面,而后给LiveData设置监听器,当数据改变的时候,会自动调用监听器。与Lifecycle绑定,当Activity被回收以后不会被触发监听。配合单例模式,能够很轻松的实如今一处修改数据,多处activity,fragment收到通知。java
DataBinding能够让你的的UI代码变得至关干净利落。它能够把页面逻辑从你的代码中提取出来。让你的代码更加专一处理其余事情。android
咱们把DataBinding的ViewModel设置成LiveData,在LiveData的监听器中调用DataBinding的刷新。这项在任何地方修改ViewModel,UI就会自动更新。bash
接下来,举个例子。咱们在上面的输入框输入文本。下面的文本框会实时反映输入的内容。app
首先是配置环境,我使用的是AndroidStudio3.0 Beta1 Project的gradle以下:maven
// 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-beta1'
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
}
复制代码
Module的gradle以下:ide
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:compiler:3.0.0-beta1'
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.constraint: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
}
复制代码
比较重要的是dataBinding {enabled = true}开启databing。布局
下面开始撸代码。 首先是ViewModel类,也是一个LiveData类。gradle
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>()
}
复制代码
这个类里面只有2个字段,分别对应界面上的输入框的内容,和文本框的显示内容。 而后是布局文件acticity_main.xmlui
<?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>
复制代码
首先最顶层的布局是layout,而后下面第一个是data域,是声明数据的地方。后面就是正常的布局。咱们首先声明了一个SearchViewMode类型的对象model。而后再TextView中进行绑定android:text="@{model.show_string.value}"。这里的**.value**是LiveData的取值的方式。
而后是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 = "等待输入"
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()
})
}
}
复制代码
说明一下**var binding = DataBindingUtil.setContentView(this, R.layout.activity_main)**把布局加载进来,这里要注意的是ActivityMainBinding这个类可能一开始没有生成,能够尝试rebuild一下,或者重启IDE。 获取到binding对象以后,就能够给对象绑定ViewModel了,也就是代码中的searchViewModel。
咱们使用binding对象.控件ID来拿到控件对象。好比:
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) {
}
})
复制代码
在监听器中修改LiveData的值。 由于咱们设置了LiveData的观察者
binding.model?.show_string?.observe( this@MainActivity, Observer{
Log.e("TAG",binding.model?.show_string?.value)
Log.e("TAG",binding.hasPendingBindings().toString())
binding.invalidateAll()
})
复制代码
当数据修改后这里就会被调用。这里的第一个参数this,是LifecycleActivity,因此这个监听器绑定了MainActvity的生命周期。这里使用了binding.invalidateAll(),而没有使用binding.executePendingBindings()是由于这里改变LiveData的value后,binding.hasPendingBindings()返回false,也就是说,databinding没有感知到数据的改变,因此不会刷新界面。