Android Databinding(一)

2015年12月24日

[TOC]

1换吧、環(huán)境需要:

1.Android 2.1 (API level 7+)
2.Gradle 1.5.0-alpha1
3.Android Studio 1.3

2沾瓦、環(huán)境搭建

在build.gradle的android中加入如下字段,等待系統(tǒng)重新編譯贯莺。

android{
        ...
        dataBinding {
            enabled = true
        }
        ...
}

3宁改、快速開始

1、編寫布局布局文件
和傳統(tǒng)的布局文件不同爹耗,databinding的布局文件的跟標(biāo)簽為layout,他有兩個(gè)子標(biāo)簽潭兽,分別為data和原始布局標(biāo)簽锅论,也就是說在原來的布局基礎(chǔ)上多加了一層layout,然后里面又多了一個(gè)data標(biāo)簽最易。在寫完布局文件之后別忘記MakeProject一下,以便系統(tǒng)自動(dòng)生成對應(yīng)的類剔猿,類名為布局文件的名字首字母大寫归敬。

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 配置變量汪茧,name字段為下面想要引用的類舱污,type為全類名,
    AS中快捷鍵ctrl+shift+alt+c -->
    <data>
        <variable
            name="person"
            type="com.znke.hellodatabinding.Person"/>
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <!-- 需要填充的字段用@{}表示 -->
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="25sp"
            android:text="@{person.name}"
            />
        <!-- 這里要轉(zhuǎn)換一下,不然會(huì)引用int值所對應(yīng)的R文件中的id -->
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="25sp"
            android:text="@{String.valueOf(person.age)}"
            />
    </LinearLayout>
</layout>

2珠插、編寫數(shù)據(jù)對象
一個(gè)簡單POJO即可

public class Person {
    public final String name;
    public final int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

3、在Acticity中進(jìn)行綁定
在Acticity的onCreate(一個(gè)參數(shù))方法里面進(jìn)行綁定捻撑。

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //當(dāng)編寫完布局文件的時(shí)候,他會(huì)自動(dòng)生成一個(gè)對應(yīng)的類布讹,名字為布局文件名稱+Binding
        ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        Person person = new Person("liucl", 22);
        //綁定
        binding.setPerson(person);
    }

*** 注意:***編譯過中程如果出現(xiàn)xxx.databingding不存在琳拭,那么就是你布局文件寫錯(cuò)了描验。仔細(xì)檢查坑鱼,現(xiàn)在as還不支持語法提示呼股。

運(yùn)行正常如下:


quickstart
quickstart

成功了,就是這三步2帧O猎啊唱矛!

4管闷、綁定點(diǎn)擊事件

Databinding支持把事件綁定到對象中窃肠,使用方法和上面大同小異
1铭拧、編寫事件對象

public class ClickEvent {

    public void click(View v){
        Toast.makeText(v.getContext(), "測試成功 \n Context對象為"
                + v.getContext().toString()
                + "\n View對象為"
                + v.toString(),
                Toast.LENGTH_SHORT).show();
    }

}

在這里我們吐司出v所在Context對象和View對象以及他所屬的布局呕臂。
2、修改我們的布局文件
首先新建一個(gè)variable引入這個(gè)類谜洽。在data字段中加入

<variable
    name="event"
    type="com.znke.hellodatabinding.ClickEvent"/>

其實(shí),我們可以使用import直接導(dǎo)入這個(gè)類实束,值得注意的是咸灿,這個(gè)區(qū)別于javaimport關(guān)鍵字,java中這個(gè)是導(dǎo)入包审胸,而這個(gè)是導(dǎo)入類歹嘹。完整的data代碼如下:

<data>
    <import type="com.znke.hellodatabinding.Person"/>
    <import type="com.znke.hellodatabinding.ClickEvent"/>
    <variable
        name="person"
        type="Person"/>
    <variable
        name="event"
        type="ClickEvent"/>
</data>

之后材蛛,我們在布局文件中加入一個(gè)Button,在onClick屬性中引用這個(gè)類

<Button
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="測試"
    android:onClick="@{event.click}"/>

最后別忘記在Acticity中綁定!6股汀!

...
    binding.setEvent(new ClickEvent());
...

運(yùn)行正常如下:


quickstart
quickstart

5、Include對象傳遞

Databinding支持include對象傳遞宣蔚,在A布局里面的對象可以傳遞到他include進(jìn)來的布局,

  1. 在A布局里定義號自定義命名空間。xmlns:app="http://schemas.android.com/apk/res-auto"下面要用到亩冬。
  2. A布局里面的include標(biāo)簽
    <include layout="@layout/include_click"
        app:event="@{event}"/>
  1. B布局代碼
    在B中也要引用一個(gè)傳遞過來的類,這個(gè)布局不用在Acticity中綁定。看過這個(gè)代碼之后巍糯,你可能回想怎么不用merge優(yōu)化呢祟峦,——暫時(shí)不支持
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <variable
            name="event"
            type="com.znke.hellodatabinding.ClickEvent"/>
    </data>

    <!-- 暫不支持merge標(biāo)簽 -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="測試"
            android:onClick="@{event.click}"/>
    </LinearLayout>
</layout>

6、表達(dá)式符號

布局文件支持這些表達(dá)式距淫,我直接引用谷歌文檔
https://developer.android.com/tools/data-binding/guide.html

Mathematical  + - / * %
String  + 這個(gè)符號可能會(huì)引起引號沖突,需把文字放到資源文件
Logical  && ||
Binary & | ^
Unary + - ! ~
Shift >> >>> <<
Comparison == > < >= <=
instanceof
Grouping ()
Literals - character, String, numeric, null
Cast
Method calls
Field access
Array access []
Ternary operator ?:

7、綁定對象與視圖堂污,使他們能聯(lián)動(dòng)

通過更改對象,視圖自動(dòng)就會(huì)隨之改變式镐,這個(gè)功能實(shí)現(xiàn)View與model層邏輯代碼的解耦和。
谷歌給出兩種方法

  1. Observable Objects
    將你的POJO繼承BaseObservable,這個(gè)類實(shí)現(xiàn)了Observable禽作。可以實(shí)現(xiàn)POJO值改變幢妄,framework層會(huì)自動(dòng)更新布局文件數(shù)據(jù)
private static class Person extends BaseObservable {
       private String name;
       private String age;
       @Bindable
       public String getName() {
           return name;
       }
       @Bindable
       public String getAge() {
           return age;
       }
       public void setName(String name) {
           this.name = name;
           notifyPropertyChanged(BR.name);
       }
       public void setAge(String age) {
           this.age = age;
           notifyPropertyChanged(BR.age);
       }
}
  1. ObservableFields
    其實(shí)他繼承了BaseObservable這個(gè)類忍法,在他的泛型中添上你的類型衍锚。同時(shí)
    ObservableBoolean, ObservableByte, ObservableChar, ObservableShort, ObservableInt, ObservableLong, ObservableFloat, ObservableDouble,ObservableParcelable
    也都是繼承了BaseObservable。
public class Person {
        public ObservableField<String> name = new ObservableField<>();
        public ObservableInt age = new ObservableInt();
}

注:谷歌文檔也給了一個(gè)Observable Collections,但我沒試驗(yàn)成功后专,但是使用上面那個(gè)方法,是可以實(shí)現(xiàn)集合更改的。

通過上面的修改后甘畅,無論在那里改這個(gè)對象里面的值函似,相應(yīng)的布局文件里面的引用都會(huì)隨之改變准给。

8、拋棄你的findViewById()

有了Databinding再也不用謝冗長的findViewById()了,框架會(huì)為你自動(dòng)生成的BR文件。
首先在我們的布局文件中莫绣,為我們兩個(gè)TextView加上id,回到Acticity中的Binding對象,是不是多出了兩個(gè)屬性。

    binding.tvText1.setText("");
    binding.tvText2.setText("");

這樣你就可以直接給他設(shè)置文本了,但是有一種更好的方法,直接binding.setVariable(com.znke.hellodatabinding.BR.person,new Person());就可以直接給布局文件中的變量賦值。

BR存儲了布局中data標(biāo)簽中的variable,相當(dāng)于R文件剿骨。

9、Attribute Setters(屬性設(shè)置)

這東西就好像Button里面的onClick屬性嫡秕,然后給他在Acticity里面寫一個(gè)對應(yīng)的實(shí)現(xiàn)方法牙甫。他的強(qiáng)大之處就是它可以什么都向里面設(shè)置。不關(guān)是點(diǎn)擊事件。他對于的實(shí)現(xiàn)方法只需要用一個(gè)注解聲明就可以了阿蝶,寫在那里都可以爽丹,即使是一個(gè)沒有使用的java文件。
通過一個(gè)Demo來說明碑宴,他有一個(gè)輸入框延柠,輸入框輸入文字雹仿,上面的TextView也會(huì)隨之改變胧辽,這里用到了屬性設(shè)置對象綁定
布局代碼

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="輸入內(nèi)容"
        app:textwatcher="@{person}"/>

屬性設(shè)置代碼

public class BindingAdapter {

    private static final String TAG = BindingAdapter.class.getSimpleName();

    /**
     * 添加上這個(gè)注解悄蕾,方法為靜態(tài)無返回值票顾,
     * 方法有兩個(gè)參數(shù)础浮,第一個(gè)是控件本身帆调,第二個(gè)為傳進(jìn)來的對象
     * 注意這個(gè)方法會(huì)被調(diào)用多次,其中會(huì)有對象為空的情況。So...
     *
     * @param e      控件本身
     * @param person 傳進(jìn)來的對象
     */
    @android.databinding.BindingAdapter({"app:textwatcher"})
    public static void editTextWatcher(final EditText e,final Person person) {
        if (person != null) {
            e.addTextChangedListener(new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                }

                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {
                }

                @Override
                public void afterTextChanged(Editable s) {
                    person.name.set(s.toString());
                    e.setSelection(s.length());
                }
            });
        }
    }
}

BindingAdapter生命周期所在
View所在ActivityonCreate方法之后豆同。當(dāng)然番刊,自定義監(jiān)聽除外

12-21 11:39:51.289 3388-3388/? E/TAG: onFinishInflate: 
12-21 11:39:51.295 3388-3388/? E/TAG: onCreate: null
12-21 11:39:51.331 3388-3388/? E/TAG: initAdapter: 
12-21 11:39:51.331 3388-3388/? E/TAG: initManager: 
12-21 11:39:51.333 3388-3388/? E/TAG: onAttachedToWindow: 
12-21 11:39:51.338 3388-3388/? E/TAG: onMeasure: 
12-21 11:39:51.406 3388-3388/? E/TAG: onLayout: 
12-21 11:39:51.429 3388-3388/? E/TAG: onMeasure: 
12-21 11:39:51.431 3388-3388/? E/TAG: onLayout: 
12-21 11:39:51.433 3388-3388/? E/TAG: onDraw: 
12-21 11:39:51.502 3388-3388/? E/TAG: onMeasure: 
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市影锈,隨后出現(xiàn)的幾起案子芹务,更是在濱河造成了極大的恐慌,老刑警劉巖鸭廷,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件枣抱,死亡現(xiàn)場離奇詭異,居然都是意外死亡辆床,警方通過查閱死者的電腦和手機(jī)佳晶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來讼载,“玉大人轿秧,你說我怎么就攤上這事∽傻蹋” “怎么了菇篡?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長一喘。 經(jīng)常有香客問我驱还,道長,這世上最難降的妖魔是什么凸克? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任议蟆,我火速辦了婚禮,結(jié)果婚禮上触徐,老公的妹妹穿的比我還像新娘咪鲜。我一直安慰自己,他們只是感情好撞鹉,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布疟丙。 她就那樣靜靜地躺著颖侄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪享郊。 梳的紋絲不亂的頭發(fā)上览祖,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天,我揣著相機(jī)與錄音炊琉,去河邊找鬼展蒂。 笑死,一個(gè)胖子當(dāng)著我的面吹牛苔咪,可吹牛的內(nèi)容都是我干的锰悼。 我是一名探鬼主播,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼团赏,長吁一口氣:“原來是場噩夢啊……” “哼箕般!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起舔清,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤丝里,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后体谒,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體杯聚,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年抒痒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了幌绍。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,769評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡评汰,死狀恐怖纷捞,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情被去,我是刑警寧澤主儡,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站惨缆,受9級特大地震影響糜值,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜坯墨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一寂汇、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧捣染,春花似錦骄瓣、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽畔勤。三九已至,卻和暖如春扒磁,著一層夾襖步出監(jiān)牢的瞬間庆揪,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工妨托, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留缸榛,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓兰伤,卻偏偏與公主長得像内颗,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子医清,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,678評論 2 354

推薦閱讀更多精彩內(nèi)容