【1】导入依赖
implementation 'androidx.databinding:databinding-runtime:4.2.2'
【2】 在app模块下的 build.gradle 文件添加内容
android {
...
dataBinding {
enabled true
}
}
或者
android {
...
buildFeatures {
viewBinding true
dataBinding true
}
}
另外,如果在 android 闭包下没有指定 java 1.8 版本的话,需要添加:
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
【3】 布局
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
</LinearLayout>
</layout>
layout:用作布局的根节点,只能包裹一个View标签,且不能包裹merge标签
data:Data Binding的数据,只能存在一个data标签
<data class="ActivityMainBinding">
</data>
data 的 class 用来自定义代码中Activity中的ViewBinding使用的<ActivityMainBinding>的名称。
<data> 标签中可以有 <import> 和 <variable> 两大标签:
<data class="ActivityMainBinding">
<import
type="com.yunchong.jetpack.model.LoginModel" />
<variable
name="loginModel"
type="LoginModel" />
</data>
import 用于导入一个类,variable 用于定义一个变量,变量 loginModel 需要和 view 绑定:
private lateinit var binding : ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
val loginModel = LoginModel(this, "zhangsan", "123456");
binding.loginModel = loginModel
}
当然,setContentView 也有所变化。
import 可以配置别名:
<data class="ActivityMainBinding">
<import
alias="LoginModelAlias"
type="com.yunchong.jetpack.model.LoginModel" />
<variable
name="loginModel"
type="LoginModelAlias" />
</data>
variable 定义的对象在xml中的使用:
<data class="ActivityMainBinding">
<variable
name="loginModel"
type="com.yunchong.jetpack.model.LoginModel" />
</data>
private lateinit var binding : ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
val loginModel = LoginModel(this, "zhangsan", "123456");
binding.loginModel = loginModel
}
<?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 class="ActivityMainBinding">
<variable
name="loginModel"
type="com.yunchong.jetpack.model.LoginModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/tv_activity_main_account"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="账号:"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:textSize="26sp"/>
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/et_activity_main_account"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textSize="26sp"
android:hint="输入账号"
android:onTextChanged="@{() -> loginModel.accountNameChanged()}"
android:text="@={loginModel.accountNameField.get()}"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBaseline_toBaselineOf="@id/tv_activity_main_account"
app:layout_constraintLeft_toRightOf="@id/tv_activity_main_account"/>
<TextView
android:id="@+id/tv_activity_main_pwd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="密码:"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_activity_main_account"
android:textSize="26sp"/>
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/et_activity_main_pwd"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textSize="26sp"
android:hint="输入密码"
android:onTextChanged="@{() -> loginModel.passwordChanged()}"
android:text="@={loginModel.passwordField.get()}"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBaseline_toBaselineOf="@id/tv_activity_main_pwd"
app:layout_constraintLeft_toRightOf="@id/tv_activity_main_pwd"/>
<androidx.appcompat.widget.AppCompatButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingVertical="10dp"
android:paddingHorizontal="20dp"
android:textSize="20sp"
android:enabled="@{(loginModel.accountNameField.get().isEmpty() || loginModel.passwordField.get().isEmpty()) ? false : true}"
android:onClick="@{() -> loginModel.login()}"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:text="登录"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
在xml布局中使用 `android:text="@{}"` 将数据和view绑定,但仅仅是单向绑定,当数据变化的时候,view 也会跟着改变。
当我们想改变布局中的数据时,只需要变化 model 中的值即可,而不需要主动修改布局中的数据显示;
但是,当布局中的数据发生变化时,model 中数据是无法发生改变的。
为了解决`单向绑定`的弊端,提出了 `双向绑定`。
`@{}` 是单向绑定, `@={}` 是双向绑定,单向绑定和双向绑定的区别就是有无 `=` 的区别。
双向绑定:当 model 发生变化时,布局中的数据也跟着改变;
当布局中的数据发生改变时, model 也发生改变。
另外,注意布局中:
android:onTextChanged
android:enabled
android:onClick
的使用。
下面,贴出model代码:
/**
* 登录Model
*/
class LoginModel(context: Context, accountName : String, password : String) {
val context: Context = context;
val accountNameField = ObservableField<String>(accountName)
val passwordField = ObservableField<String>(password)
/**
* 输入账号变化时执行
*/
fun accountNameChanged() {
Log.d("yunchong", accountNameField.get() as String)
}
/**
* 输入密码时执行
*/
fun passwordChanged() {
Log.d("yunchong", passwordField.get() as String)
}
/**
* 登录
*/
fun login() {
if ("zhangsan" == accountNameField.get() && "123456" == passwordField.get()) {
Toast.makeText(context, "登录成功...", Toast.LENGTH_SHORT).show()
startActivity<DataActivity>(context) {
putExtra("acountName", accountNameField.get())
putExtra("password", passwordField.get())
}
} else {
Toast.makeText(context, "登录失败...", Toast.LENGTH_SHORT).show()
}
}
}
Activity 的跳转是被封装好的,直接拿来用即可:
/**
* 启动 Activity
*/
inline fun <reified T> startActivity(context: Context, block: Intent.() -> Unit) {
val intent = Intent(context, T::class.java)
intent.block()
context.startActivity(intent)
}
[本章完...]
网友评论