基礎(chǔ)理解
DataBinding針對每個(gè)Activity的布局猾浦,在編譯階段屹电,生成一個(gè)ViewDataBinding類的對象,該對象持有Activity要展示的數(shù)據(jù)和布局中的各個(gè)view的引用(也就解決了findViewById的問題)跃巡,同時(shí)該對象還有將數(shù)據(jù)分解到各個(gè)view危号,在UI線程上更新數(shù)據(jù),監(jiān)控?cái)?shù)據(jù)的變化素邪,實(shí)時(shí)更新等功能外莲,這樣要展示的數(shù)據(jù)和展示它的布局就緊密的聯(lián)系在一起了。
簡單例子
首先我們先建立一個(gè)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ù)據(jù)綁定類的基類埠帕。
ViewDataBinding的實(shí)例一般是DataBindingUtil調(diào)用setContentView(Activity activity, int layoutId)方法生成。
2仇味、BR
BR中的常量是一種標(biāo)識符照宝,它對應(yīng)一個(gè)會發(fā)生變化的數(shù)據(jù)蛇受,當(dāng)數(shù)據(jù)改變后,你可以用該標(biāo)識符通知DataBinding厕鹃,很快兢仰,DataBinding就會用新的數(shù)據(jù)去更新UI乍丈。
3、DataBindingUtil
可以從layout創(chuàng)建數(shù)據(jù)綁定類把将。
關(guān)于他們之間的關(guān)系可以看這篇
DataBinding實(shí)現(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[]" />
<!-- 為集合定義對應(yīng)的索引 -->
<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 導(dǎo)入android.view.View.OnClickListener,并制定其點(diǎn)擊事件秸弛。
<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
});
表達(dá)式
在xml文件中還是支持表達(dá)式的,比如說如下:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{error ? "yes" : "no"}'/>
支持的表達(dá)式:
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中有一個(gè)靜態(tài)方法
public static String getLevel(){
return "0";
}
然后在 xml 的 data 節(jié)點(diǎn)中導(dǎo)入:
<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
要實(shí)現(xiàn) Observable Binding洪碳,首先得有一個(gè)實(shí)現(xiàn)了 android.databinding.Observable 的類递览,為了方便,Android 原生提供了已經(jīng)封裝好的一個(gè)類 - BaseObservable瞳腌,并且實(shí)現(xiàn)了監(jiān)聽器的注冊機(jī)制绞铃。
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);
}
}
通過代碼可以看出,當(dāng)數(shù)據(jù)發(fā)生變化時(shí)還是需要手動發(fā)出通知嫂侍。 通過調(diào)用notifyPropertyChanged(BR.firstName)來通知系統(tǒng) BR.firstName 這個(gè) entry 的數(shù)據(jù)已經(jīng)發(fā)生變化儿捧,需要更新 UI。