DataBinding是對(duì)MVVM架構(gòu)的最好詮釋,一直以來邏輯,數(shù)據(jù)模型,和界面之間的關(guān)系都沒有一個(gè)很好的平衡,MVP架構(gòu)會(huì)使大量的邏輯代碼都集中在Presenter中,而DataBinding可以很好的平衡這些之間的關(guān)系
工程配置
之前看到網(wǎng)上許多資料都是需要配置DataBinding的依賴,但是我使用的是新版的gradle,沒有出現(xiàn)需要配置依賴的地方,只需要在gradle(app的gradle)中加入以下代碼:
dataBinding {
enabled true
}
數(shù)據(jù)對(duì)象的綁定
首先新建一個(gè)工程,有一個(gè)MainActivity以及一個(gè)activity_main.xml的布局文件,當(dāng)然你叫別的名字也無所謂。然后建一個(gè)數(shù)據(jù)模型類,如下:
public class Person extends BaseObservable {
private String name;
private String age;
private String sex;
public Person(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;
}
public void setSex(String sex) {
this.sex = sex;
notifyPropertyChanged(BR.sex);
}
public String getSex() {
return sex;
}
}
然后修改布局文件activity_main.xml
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<import type="databind.android.com.testdatabind.Person" />
<variable
name="animal"
type="databind.android.com.testdatabind.Animal" />
<variable
name="person"
type="Person" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{person.name}"
android:textColor="#000000"
android:textSize="18dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{person.age}"
android:textColor="#000000"
android:textSize="14dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{person.sex}"
android:textColor="#000000"
android:textSize="14dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{animal.name}"
android:textColor="#000000"
android:textSize="18dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{animal.age}"
android:textColor="#000000"
android:textSize="14dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{animal.sex}"
android:textColor="#000000"
android:textSize="14dp" />
</LinearLayout>
</layout>
與以往的布局文件不同的是,這類布局文件會(huì)有一個(gè)data的標(biāo)簽,import的語法與java一樣,不過多介紹,variable便是一個(gè)變量,在布局文件中定義變量,是不是很稀奇,這正是data binding的核心所在。
接下來我們?cè)趯?duì)應(yīng)的activity中添加如下代碼:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
Person person = new Person("umeng share","5");
Animal animal = new Animal("cat","5");
binding.setPerson(person);
binding.setAnimal(animal);
person.setSex("male");
animal.setSex("female");
}
ActivityMainBinding這個(gè)類是根據(jù)剛才的布局文件自動(dòng)生成的,因?yàn)閯偛挪季治募衋ctivity_main所以自動(dòng)生成類ActivityMainBinding,如果叫activity_ddd,就會(huì)自動(dòng)生成ActivityDddBinding。
此時(shí)運(yùn)行程序,就會(huì)顯示對(duì)應(yīng)的字符,沒有了findviewbyid是不是清晰多了。
點(diǎn)擊事件
如果你認(rèn)為只有這些功能,那就大錯(cuò)特錯(cuò)了,接下來再看一下如何添加點(diǎn)擊事件。
布局中添加如下代碼(在哪添加不用說了吧,當(dāng)然是data標(biāo)簽下):
<variable
name="click"
type="android.view.View.OnClickListener" />
以及布局中添加:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{click}"
android:textColor="#000000"
android:textSize="14dp" />
同時(shí)我們?cè)贏ctivity中添加如下代碼:
binding.setClick(new View.OnClickListener() {
@Override
public void onClick(View view) {
}
});
通過以上兩個(gè)例子可以看出我們可以在java代碼中通過binding設(shè)置變量的具體內(nèi)容,然后在布局文件中接受變量的內(nèi)容,然后通過布局顯示出來。
其它類型
除此之外,所有java的集合類數(shù)據(jù)類型,都可以支持,比如List
我們修改布局文件:
<import type="java.util.ArrayList" />
<variable
name="list"
type="ArrayList<String>" />
<variable
name="listKey"
type="int" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{click}"
android:text="@{list[listKey]}"
android:textColor="#000000"
android:textSize="14dp" />
對(duì)應(yīng)的java代碼:
binding.setList(list);
binding.setListKey(0);
要注意的是布局文件中<符號(hào)會(huì)被轉(zhuǎn)義,所以我們用<,在布局文件中會(huì)報(bào)紅,但是不影響編譯
方法的調(diào)用
我們新建一個(gè)方法類:
public class StringUtil {
public static String cut( String word) {
if (word.length()>4){
word = word.substring(0,4);
}
return word;
}
}
在布局文件中可以用如下方式調(diào)用:
<import type="databind.android.com.testdatabind.StringUtil" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{StringUtil.cut(person.name)}" />
檢測變量的變化
在實(shí)際應(yīng)用中,所有的變量不可能是一成不變的,如果變量的值發(fā)生變化如何在界面上更新呢?
我們需要修改一下數(shù)據(jù)模型類:
package databind.android.com.testdatabind.detail;
import android.databinding.BaseObservable;
import android.databinding.Bindable;
import databind.android.com.testdatabind.BR;
/**
* Created by wangfei on 17/1/1.
*/
public class Person extends BaseObservable {
private String name;
private String age;
private String sex;
public Person(String name, String age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
notifyPropertyChanged(BR.name);
}
public void setAge(String age) {
this.age = age;
notifyPropertyChanged(BR.age);
}
@Bindable
public String getName() {
return this.name;
}
@Bindable
public String getAge() {
return this.age;
}
public void setSex(String sex) {
this.sex = sex;
notifyPropertyChanged(BR.sex);
}
@Bindable
public String getSex() {
return sex;
}
}
在get方法中加上注解@Bindable,同時(shí)在set方法中加入 notifyPropertyChanged(BR.xxx);
同時(shí)在java文件中,需要變動(dòng)的地方,直接設(shè)置變量的值即可觸發(fā)界面的變化:
person.setName("點(diǎn)擊按鈕產(chǎn)生了變化");
什么取代了findViewById
正常編程下我們都是通過findViewById獲得布局文件中各組件的對(duì)象,那么在data binding下如何獲取呢?
其實(shí)非常簡單,例如有如下布局:
<TextView
android:id="@+id/mutable"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{realperson.sex}"
android:textColor="#000000"
android:textSize="14dp" />
ID是mutable,那么在java文件中的binding會(huì)自動(dòng)生成對(duì)應(yīng)的變量mutable
binding.mutable.setText("點(diǎn)擊事件");
表達(dá)式
除此之外,還可以在布局文件中運(yùn)用一些基本的表達(dá)式,如下:
<TextView
android:text="@{person.sex}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="@{person.isMan ? View.VISIBLE : View.GONE"/>
總結(jié)
除了上面介紹的基本方法,data Binding當(dāng)然還有很多高級(jí)方法,我們需要在實(shí)際應(yīng)用中去學(xué)習(xí),這里只做了簡單的介紹,但是不難看出,如果這種方式使用純熟了,開發(fā)界面類應(yīng)用真的會(huì)省去很多麻煩。
我在這里寫了一個(gè)簡單的demo,感興趣的朋友可以參考一下:
https://github.com/mymdeep/databinding