
运行环境
- Android Studio 3.5
- JDK 1.8.0_202
- Kotlin
搭建环境(Build Environment)
申请 Kotlin-Kapt 插件, 开启数据绑定(Data Binding)
app模块build.gradle文件中添加 dataBinding 元素
//...
apply plugin: 'Kotlin-Kapt' //申请 Kotlin-Kapt 插件
android{
//...
dataBinding{
enabled = true // 打开数据绑定
}
}
数据对象(Data Object)
class MainData(private val context: Context){
var name:String = "World"
fun onClickMethodReference(view:View){
Toast.makeText(context,
"Method Reference: android:onClick=\"@{mainData::onClickMethodReference}\"",
Toast.LENGTH_LONG).show()
}
fun onClickListenerBindings(){
Toast.makeText(context,
"Listener Bindings: android:onClick=\"@{()->mainData.onClickListenerBindings()}\"",
Toast.LENGTH_LONG).show()
}
fun onClickListenerBindingsWithParamer(view:View, context:Context){
Toast.makeText(context,
"Listener Bindings: android:onClick=\"@{(view)->mainData.onClickListenerBindings(view, context)}\"",
Toast.LENGTH_LONG).show()
}
}
绑定数据(Binding Data)
为每个布局文件生成一个绑定类(binding class),默认的,绑定类名由布局文件名加Binding后缀并大写首字母构成
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding:ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.mainData = MainData(this)
}
}
...
绑定适配器(Binding Adapters)
布局(Layout)属性适配器
object BindingAdapters{
/**
* Provide custom logic
* https://developer.android.google.cn/topic/libraries/data-binding/binding-adapters#custom-logic
*/
@BindingAdapter("android:text")
@JvmStatic fun setText(view:TextView, text: String){
Log.d("---------", text)
view.text = text
}
}
MainActivity.kt
package com.buyi.jetpack
import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Toast
import androidx.databinding.*
import com.buyi.jetpack.data.ObservableObjectUser
import com.buyi.jetpack.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding:ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.mainData = MainData(this)
binding.mainDataObservable = MainDataObservable()
}
}
class MainData(private val context: Context){
var name:String = "World"
fun onClickMethodReference(view:View){
Toast.makeText(context,
"Method Reference: android:onClick=\"@{mainData::onClickMethodReference}\"",
Toast.LENGTH_LONG).show()
}
fun onClickListenerBindings(){
Toast.makeText(context,
"Listener Bindings: android:onClick=\"@{()->mainData.onClickListenerBindings()}\"",
Toast.LENGTH_LONG).show()
}
fun onClickListenerBindingsWithParamer(view:View, context:Context){
Toast.makeText(context,
"Listener Bindings: android:onClick=\"@{(view)->mainData.onClickListenerBindings(view, context)}\"",
Toast.LENGTH_LONG).show()
}
}
class MainDataObservable:BaseObservable(){
var year:ObservableInt = ObservableInt(2019)
// Kotlin 中 Any 相当于 Java 中的 Object
var time:ObservableList<Any> = ObservableArrayList<Any>().apply {
add("20")
add("40")
}
fun onClickObservabelFields(context: Context){
year.set(2020)
Toast.makeText(context, "Observable Fields: Change year to 2020 success!!!",
Toast.LENGTH_LONG).show()
}
fun onClickObservableCollections(context: Context){
time[1] = "44"
Toast.makeText(context, "Observable Collections: Change time to 20:44 success!!!",
Toast.LENGTH_LONG).show()
}
@get:Bindable
var greeting:String = "Hello World!"
set(value) {
field = value
notifyPropertyChanged(BR.greeting)
}
fun changeGreeting(context: Context){
greeting = "Hello Buyi!"
Toast.makeText(context, "Observable Objects",
Toast.LENGTH_LONG).show()
}
}
activity_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>
<variable
name="user"
type="com.buyi.jetpack.data.ObservableObjectUser" />
<variable
name="mainDataObservable"
type="com.buyi.jetpack.MainDataObservable" />
<variable
name="mainData"
type="com.buyi.jetpack.MainData" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Layouts and binding expressions"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:onClick="@{mainData::onClickMethodReference}"
android:text="Method Reference"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:onClick="@{()->mainData.onClickListenerBindings()}"
android:text="Listener Bindings"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button2" />
<Button
android:id="@+id/button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:onClick="@{(view)->mainData.onClickListenerBindingsWithParamer(view, context)}"
android:text="Listener Bindings With Parameter"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button3" />
<!-- Work with observable data objects-->
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="Work with observable data objects"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button4" />
<Button
android:id="@+id/button5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:onClick="@{()->mainDataObservable.onClickObservabelFields(context)}"
android:text="Observable Fields"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView2" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:text="@{String.valueOf(mainDataObservable.year)}"
app:layout_constraintBottom_toBottomOf="@+id/button5"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/button5" />
<Button
android:id="@+id/button7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:onClick="@{()->mainDataObservable.onClickObservableCollections(context)}"
android:text="Observable Collections"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button5" />
<TextView
android:id="@+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:text="@{mainDataObservable.time[0] + ` : ` + mainDataObservable.time[1]}"
app:layout_constraintBottom_toBottomOf="@+id/button7"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/button7" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:onClick="@{()->mainDataObservable.changeGreeting(context)}"
android:text="Observable Objects"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button7" />
<TextView
android:id="@+id/hw"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:text="@{mainDataObservable.greeting}"
app:layout_constraintBaseline_toBaselineOf="@+id/button"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>