基礎理解
DataBinding針對每個Activity的布局,在編譯階段,生成一個ViewDataBinding類的對象,該對象持有Activity要展示的數(shù)據和布局中的各個view的引用(也就解決了findViewById的問題),同時該對象還有將數(shù)據分解到各個view,在UI線程上更新數(shù)據,監(jiān)控數(shù)據的變化,實時更新等功能,這樣要展示的數(shù)據和展示它的布局就緊密的聯(lián)系在一起了。
簡單例子
首先我們先建立一個java bean。
public class User {
private String name;
private String age;
public User(String name, String age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(String age) {
this.age = age;
}
public String getName() {
return this.name;
}
public String getAge() {
return this.age;
}
}
布局文件
<?xml version="1.0" encoding="utf-8"?>
<layout>
<data>
<variable
name="user"
type="app.ylm.com.studyproject.User"/>
</data>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:text="@{user.name}"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:text="@{user.age}"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</layout>
然后會自動生成Binding類,命名規(guī)則為:
xml通過文件名生成,使用下劃線分割大小寫,后綴加上Binding。比如activity_demo.xml,則會生成ActivityDemoBinding。在Activity中使用。
public class MainActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DatabindingBinding binding = DataBindingUtil.setContentView(this,R.layout.databinding);
User user = new User("tony","12");
binding.setUser(user);
}
}
這樣就可以使用了
主要組成部分
1、ViewDataBinding
數(shù)據綁定類的基類。
ViewDataBinding的實例一般是DataBindingUtil調用setContentView(Activity activity, int layoutId)方法生成。
2、BR
BR中的常量是一種標識符,它對應一個會發(fā)生變化的數(shù)據,當數(shù)據改變后,你可以用該標識符通知DataBinding,很快,DataBinding就會用新的數(shù)據去更新UI。
3、DataBindingUtil
可以從layout創(chuàng)建數(shù)據綁定類。
關于他們之間的關系可以看這篇
DataBinding實現(xiàn)原理探析
拓展
變量定義
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<import type="android.graphics.Bitmap" />
<import type="java.util.ArrayList" />
<import type="java.util.HashMap" />
<!-- 集合的定義 -->
<variable
name="list"
type="ArrayList<String>" />
<variable
name="map"
type="HashMap<String, String>" />
<variable
name="array"
type="String[]" />
<!-- 為集合定義對應的索引 -->
<variable
name="listKey"
type="int" />
<variable
name="mapKey"
type="String" />
<variable
name="arrayKey"
type="int" />
<!-- 字符串,布爾值和int的用法-->
<variable
name="str"
type="String"/>
<variable
name="error"
type="boolean"/>
<variable
name="num"
type="int" />
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{list[listKey]}"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{map[`name`]}"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{array[0]}"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{str}"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{String.valueOf(num)}"/>
</LinearLayout>
</layout>
事件的綁定
可以直接在 xml 導入android.view.View.OnClickListener,并制定其點擊事件。
<variable
name="clickListener"
type="android.view.View.OnClickListener" />
...
android:onClick="@{clickListener}"
...
holder.binding.setClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//do something
});
表達式
在xml文件中還是支持表達式的,比如說如下:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{error ? "yes" : "no"}'/>
支持的表達式:
Mathematical + - / * %
String concatenation +
Logical && ||
Binary & | ^
Unary + - ! ~
Shift >> >>> <<
Comparison == > < >= <=
instanceof
Grouping ()
Literals - character, String, numeric, null
Cast
Method calls
Field access
Array access []
Ternary operator ?:
使用類方法
比如User中有一個靜態(tài)方法
public static String getLevel(){
return "0";
}
然后在 xml 的 data 節(jié)點中導入:
<import type="app.ylm.com.studyproject.User"/>
使用方法與 Java 語法一樣:
<TextView
android:text="@{User.getLevel()}"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
Observable Binding
要實現(xiàn) Observable Binding,首先得有一個實現(xiàn)了 android.databinding.Observable 的類,為了方便,Android 原生提供了已經封裝好的一個類 - BaseObservable,并且實現(xiàn)了監(jiān)聽器的注冊機制。
public class ObservableUser extends BaseObservable {
private String firstName;
private String lastName;
@Bindable
public String getFirstName() {
return firstName;
}
@Bindable
public String getLastName() {
return lastName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
notifyPropertyChanged(BR.firstName);
}
public void setLastName(String lastName) {
this.lastName = lastName;
notifyPropertyChanged(BR.lastName);
}
}
通過代碼可以看出,當數(shù)據發(fā)生變化時還是需要手動發(fā)出通知。 通過調用notifyPropertyChanged(BR.firstName)來通知系統(tǒng) BR.firstName 這個 entry 的數(shù)據已經發(fā)生變化,需要更新 UI。