DataBinding

使用

Databinding是一个支持库,可让您使用声明性格式 (而不是以编程方式) 将布局中的UI组件绑定到应用中的数据源

用于降低布局和逻辑的耦合性,使代码逻辑更加清晰。
DataBinding 能够省去我们一直以来的 findViewById() 步骤,大量减少 Activity 内的代码。

写起来安逸,读起来不安逸。

DataBinding 引入之后,操作的就是 ViewModel 中的属性

使用步骤

(1)导入依赖

1
2
3
4
5
6
android {
...
buildFeatures {
dataBinding = true
}
}

(2)将 Layout 的根布局转化为 DataBinding

Alt + Enter
选择 Convert to data binding layout

绑定

(1)绑定固定属性(赋值)

android:text = @{viewModel.name}

事件绑定

(2)绑定点击事件

onClick
android:onClick = @{(view) -> events.loadData(view,viewModel.url)}

有 LgLoginViewModel 类 和 LgClickEvent 类
LgClickEvent类 中有 loadData(view:View,viewModel:ViewModel) 方法

在 xml 中使用

1
2
3
4
5
6
7
8
9
10
11
12
13
<data>
<variable
name="viewModel"
type="com.example.login.LgLoginViewModel" />
<variable
name="events"
type="com.example.login.LgClickEvent" />
</data>

<TextView
android:onClick = "@{(view) -> events.loadData(view,viewModel)}"
/>

Fragment 中建立联系(将 xml 和 ViewModel 、 ClickEvent 之间建立联系)

1
2
3
4
binding.viewModel = loginViewMode
binding.events = LgClickEvent()
binding.lifecycleOwner = this
binding.executePendingBindings() //)方法用于立即执行绑定表达式,以确保视图在数据更改后得到更新。

(3)有了某个属性需要做处理(自定义控件属性)

(给视图绑定某个属性)

方法名 = @{参数}

绑定自定义的属性
(将我们自己设置的属性,赋予给控件)

viewModel 中 定义属性:

1
val agreementShouldSwing = MutableLiveData(false)

随便一个文件
在文件中:
给 View 添加扩展方法
添加注解 @BindingAdapter(“”)

1
2
3
4
5
6
7
//给协议视图绑定一个属性 shouldSwing,根据传入的agreementShouldSwing进行判断
@BindingAdapter("shouldSwing")
fun View.shouldSwing(swing:Boolean){
if(swing){
AnimUtils.startSwingAnimation( target: this)
}
}

在 xml 中使用
@{viewModel.agreementShouldSwing} 就相当于
将 ViewModel 中的这个值传递给 View.shouldSwing(swing:Boolean) 做操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<data>
<variable
name="viewModel"
type="com.example.login.LgLoginViewModel" />
<variable
name="events"
type="com.example.login.LgClickEvent" />
</data>


<!--相当于给TextView控件,添加了一个属性shouldSwing-->
<TextView
shouldSwing = "@{viewModel.agreementShouldSwing}"
</TextView>

双向数据绑定

@ = {} 表示法 (其中重要的是包含 “ = ” 符号) 可接收属性的数据更改,并同时监听用户更新。

1
2
3
4
<CheckBox
android:id="@+id/rememberMeCheckBox"
android:checked="@={viewmodel.rememberMe}"
/>

原理

MVC 是由工程目录结构所决定的,Activity是控制层,res xml布局属于控制层(Activity太过于臃肿,没有单一职责,耦合过度,拓展性都不好)

Databinding会卡

一般做单向,双向会比较耗性能,

使用

Model实体

Bean类继承BaseObservable

get方法使用注解标记@Bindable

//生成代码 APT技术

set方法使用notifyPropertyChanged(BR.remember_me);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class LoginViewModel extends BaseObservable {
// private Model data = ...

@Bindable
public Boolean getRememberMe() {
return data.rememberMe;
}

public void setRememberMe(Boolean value) {
// Avoids infinite loops.
if (data.rememberMe != value) {
data.rememberMe = value;

// React to the change.
saveData();

// Notify observers of a new value.
notifyPropertyChanged(BR.remember_me);
}
}
}

布局

将Layout布局文件转换成 data binding layout

1
2
3
4
<CheckBox
android:id="@+id/rememberMeCheckBox"
android:checked="@={viewmodel.rememberMe}"
/>

建立绑定关联

ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);

1
2
3
4
5
6
7
8
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
User user = new LoginViewModel("Test", "User");
binding.setRememberMeCheckBox(user);
}

Kotlin

1
2
3
4
5
6
7
8
9
class User {
val firstName = ObservableField<String>()
val lastName = ObservableField<String>()
val age = ObservableInt()
}

val nameF : ObservableField<String> by lazy { ObservableField<String>() }
val pwdF : ObservableField<String> by lazy { ObservableField<String>() }


源码

ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);

主线在bind()

面试

DataBinding使用了APT注解处理器技术,来扫描布局,生成两个布局文件,来做事情

它会想办法把data部分的截取出来,分成两个布局文件

那这两个布局文件是怎么关联的?

ActivityMainBinding类是由APT注解处理器生成的,这个类会读取tag标记,来去解析所有控件,保存到Object数组里

可能会问你这句话是不是反射?
type=”com.example.login.LgLoginViewModel” />
不是

1
2
3
4
5
6
7
8
<data>
<variable
name="viewModel"
type="com.example.login.LgLoginViewModel" />
<variable
name="events"
type="com.example.login.LgClickEvent" />
</data>

DataBinding 把布局拆成两份

动态注入tag


DataBinding是Android的一个库,它允许你在布局文件中绑定UI组件数据源,这样可以更简单地编写代码来更新UI元素。

DataBinding的原理

  1. APT预编译: 在编译时期,通过注解处理器(APT)生成绑定类,如ActivityMainBindingActivityMainBindingImpl

  2. 布局文件处理:

    处理布局时,生成两个XML文件:(它会想办法把data部分的截取出来,分成两个布局文件)

    • activity_main-layout.xml:包含DataBinding所需的布局控件信息
    • activity_main.xml:用于Android操作系统渲染的布局文件

Model如何刷新View

  1. DataBindingUtil.setContentView: 此方法将XML中的各个View赋值给ViewDataBinding,完成findViewById的任务。
  2. ViewModel层的notifyPropertyChanged: 当ViewModel层调用此方法时,ViewDataBindingImplexecuteBindings方法中处理逻辑,从而更新UI。

View如何刷新Model

  • 双向绑定: ViewDataBindingImplexecuteBindings方法中为设置了双向绑定的控件添加监听器,如在EditText上设置TextWatcher
  • 监听器回调: 当数据发生变化时,TextWatcheronTextChanged()方法会通过回调更新Model。

DataBinding的使用

  • 布局文件中的绑定: 在布局文件中,可以使用<data>标签来定义绑定的数据,并通过<variable>标签来指定数据类型和变量名。
  • 表达式语言: DataBinding支持表达式语言,允许在布局文件中直接写入逻辑代码,如条件语句、方法调用等。
  • 资源引用: 可以在布局中直接引用资源文件,如字符串、颜色等。
  • 事件绑定: 可以将事件处理器直接绑定到布局中的UI组件上。

DataBinding的优势

  • 减少样板代码: 自动化的findViewById减少了初始化UI组件的代码。
  • 提高性能: 相比传统的UI更新方式,DataBinding可以更高效地处理数据变化和UI更新。
  • 类型安全: 编译时的类型检查减少了运行时错误。
  • 维护性: 使得代码更加模块化,易于维护和测试。

DataBinding是MVVM架构中的关键组件,它通过声明性布局和绑定机制,提高了开发效率和应用性能。

Donate
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.

扫一扫,分享到微信

微信分享二维码
  • Copyrights © 2023-2025 Annie
  • Visitors: | Views:

嘿嘿 请我吃小蛋糕吧~

支付宝
微信