Android DataBinding 结合 ViewModel的使用
一、build.gradle引入对应的依赖
在build.gradle(app模块)里引入依赖,然后Sync Now一下:
android {viewBinding {enabled = true}dataBinding {enabled = true}}
完整的build.gradle代码如下所示:
plugins {id 'com.android.application'id 'org.jetbrains.kotlin.android'}apply plugin: 'kotlin-kapt'android {compileSdk 33defaultConfig {applicationId "com.check.databindingproject"minSdk 23targetSdk 33versionCode 1versionName "1.0"testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"}viewBinding {enabled = true}dataBinding {enabled = true}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}compileOptions {sourceCompatibility JavaVersion.VERSION_1_8targetCompatibility JavaVersion.VERSION_1_8}kotlinOptions {jvmTarget = '1.8'}}dependencies {implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1" // ViewModel 和 LiveDataimplementation "androidx.lifecycle:lifecycle-livedata-ktx:2.6.1" // LiveDataimplementation "androidx.activity:activity-ktx:1.7.0" // 添加 ViewModel KTX 扩展implementation 'androidx.appcompat:appcompat:1.3.0'implementation 'com.google.android.material:material:1.4.0'implementation 'androidx.constraintlayout:constraintlayout:2.0.4'testImplementation 'junit:junit:4.13.2'androidTestImplementation 'androidx.test.ext:junit:1.1.3'androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'}configurations.all {resolutionStrategy {force "org.jetbrains.kotlin:kotlin-stdlib:1.8.10"force "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.10"}}
二、转换视图成data binding layout
2、找到想要改为dataBinding视图的页面, Mac系统的按Option Enter (Windows系统的按Alt + Enter)弹出如下:
比如选中的是activity_main.xml视图文件,那么
<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout 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"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Hello World!"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout>
选择这个功能之后,就可以将当前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></data><androidx.constraintlayout.widget.ConstraintLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Hello World!"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout></layout>
整体变成了下面这种布局方式
<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></data><!-- 布局文件之前的样式 -->...</layout>
可以看到页面出现了新的Layout和data的空标签。(data 就是用来存放数据的)
改造之后的完整的代码如下所示:
<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"xmlns:app="http://schemas.android.com/apk/res-auto"><data><variablename="user"type="com.check.databindingproject.UserModel" /></data><androidx.constraintlayout.widget.ConstraintLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><TextViewandroid:id="@+id/name_text"android:layout_width="wrap_content"android:layout_height="wrap_content"app:layout_constraintTop_toTopOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintRight_toRightOf="parent"tools:text="姓名"android:text="@{`Name is ` + user.name}" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"app:layout_constraintTop_toBottomOf="@id/name_text"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"tools:text="年龄"android:text="@{`Age is ` + user.age}" /></androidx.constraintlayout.widget.ConstraintLayout></layout>
其中正常绑定某个变量的值到控件的某个元素上,可以用@{user.age},括号里面用变量替代。然后如果想在里面加上一些常量值,那么就用模板@{`Age is` + user.age}
三、创建ViewModel和Binding对象
3、创建ViewModel类
UserModel.kt
package com.check.databindingprojectimport androidx.databinding.BaseObservableimport androidx.databinding.Bindableclass UserModel(user_name: String, user_age: Int) : BaseObservable() {@get:Bindablevar name: String = user_nameset(value) {field = valuenotifyPropertyChanged(BR.name) // 触发绑定更新}@get:Bindablevar age: String = user_age.toString()set(value) {field = valuenotifyPropertyChanged(BR.age) // 触发绑定更新}}
MainViewModel.kt
package com.check.databindingprojectimport androidx.lifecycle.ViewModelclass MainViewModel : ViewModel() {val user = UserModel("Alice", 300)}
接下来到对应的Activity里,声明全局变量为视图去掉下划线改大写+binding, 比如视图为activity_main.xml,则对应声明的databinding类型变量就是ActivityMainBinding类型,如下:
MainActivity.kt
package com.check.databindingprojectimport android.os.Bundleimport androidx.appcompat.app.AppCompatActivityimport androidx.databinding.DataBindingUtilimport androidx.lifecycle.ViewModelProviderimport com.check.databindingproject.databinding.ActivityMainBindingclass MainActivity : AppCompatActivity() {private lateinit var binding: ActivityMainBindingprivate lateinit var viewModel: MainViewModeloverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)// 获取 ViewModelviewModel = ViewModelProvider(this)[MainViewModel::class.java]// 使用 DataBindingbinding = DataBindingUtil.setContentView(this, R.layout.activity_main)// 将 ViewModel 的 user 绑定到布局binding.user = viewModel.user // 如果你需要动态更改数据,可以直接修改 UserModel 的属性viewModel.user.name = "Bob"viewModel.user.age = "1300"}}
最后显示出来的效果就是