Data Binding 詳解(三)-可觀察(監(jiān)聽)的數(shù)據(jù)對象

知是行之始,行是知之成杂瘸。
文章配套的 Demohttps://github.com/muyi-yang/DataBindingDemo
Demo 支持 Java 和 Kotlin 雙語言倒淫,master 分支為 Java 語言代碼,kotlin 分支為 Kotlin 語言代碼败玉。

可觀察(observable)是指一個對象通知其他對象其數(shù)據(jù)的更改的能力敌土。 Data Binding 庫支持創(chuàng)建可觀察的對象、字段或集合运翼。普通的對象都可以用于 Data Binding返干,但是對象數(shù)據(jù)改變并不會自動更新 UI 。使用 Data Binding 可以使數(shù)據(jù)對象能夠在其數(shù)據(jù)更改時通知其他對象(稱為監(jiān)聽器)血淌。 有三種不同類型的可觀察類: 對象矩欠、字段和集合,當(dāng)其中一個可觀察的數(shù)據(jù)對象綁定到 UI 并且數(shù)據(jù)對象的值發(fā)生更改時悠夯,UI 將自動更新癌淮。

可觀察的字段

當(dāng)一個類的部分屬性要被觀察,想做到數(shù)據(jù)實時反應(yīng)到 UI 時疗疟,你可以使用通用的 Observable 類和以下特定類型的類來使字段可以被觀察:

public class ListActivity extends AppCompatActivity {
    ...
    public final ObservableField<String> name = new ObservableField<>();
    public final ObservableInt index = new ObservableInt();
    ...
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ...
        adapter = new ListAdapter();
        ...
        adapter.setItemClickListener(new ListAdapter.MyItemClickListener() {
            @Override
            public void onItemClick(View v, int position, CelebrityInfo info) {
                name.set(info.getName());
                index.set(position);
            }
        });
        ...
    }
}

這里是聲明了一個可觀察的 String 類型和 int 類型數(shù)據(jù)店诗,ObservableField 類是萬能類裹刮,它是可以包含所有對象數(shù)據(jù)的容器,調(diào)用 set() 方法賦值庞瘸,調(diào)用 get() 方法取值捧弃。因為它是一個可觀察的數(shù)據(jù)對象(內(nèi)部通過觀察者模式實現(xiàn)),所以當(dāng)你調(diào)用 set() 方法賦值時擦囊,它會自動通知綁定了 get() 方法的 UI 刷新數(shù)據(jù)违霞,這里點擊列表的 item 時界面上會自動更新名字和 item 的索引。布局中的使用:

<!--activity_list.xml-->
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="activity"
            type="com.example.databindingdemo.ListActivity" />
        ...
    </data>
        ...
        <TextView
            ...
            android:text="@{@string/click_info(activity.name, activity.index)}"
            />
        ...
</layout>

可運行 Demo 查看具體效果瞬场。

可觀察的集合

很多情況下我們會使用一些集合數(shù)據(jù)买鸽,Data Binding 中也提供了相應(yīng)的可觀察的集合類:ObservableArrayMapObservableArrayList贯被。比如:

public class ListActivity extends AppCompatActivity {
    ...
    public final ObservableArrayList<CelebrityInfo> listData = new ObservableArrayList<>();
    ...
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ...
        adapter = new ListAdapter();
        binding.setAdapter(adapter);
        adapter.setData(listData);
        ...
    }
}

這里聲明了一個 ObservableArrayList 集合眼五,它里面裝著列表中的數(shù)據(jù)。在布局中顯示了列表的大型睢:

<!--activity_list.xml-->
<TextView
            ...
            android:text="@{@string/list_size(activity.listData.size())}"
            ... />

當(dāng)列表中的數(shù)據(jù)發(fā)生改變時看幼,界面會自動刷新,并顯示列表當(dāng)前的大小幌陕。便于觀察效果诵姜,我延遲了 2 秒后往 listData 中插入了一個數(shù)據(jù):

 private void getCelebrityList() {
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                CelebrityInfo brock = new CelebrityInfo();
                brock.setName("布洛克·萊斯納");
                brock.setWeight(130);
                brock.setRetire(false);
                brock.setIncome(1000);
                brock.setPhoto(R.drawable.brock);
                listData.add(1, brock);
            }
        }, 2000);
      ...
}

當(dāng)你運行 Demo 后可看到具體效果。

ObservableArrayMap 的使用也是類似搏熄,和普通 Map 的使用也沒什么區(qū)別茅诱,只不過它是一個可觀察的 Map,在數(shù)據(jù)發(fā)送改變時會通知綁定的 UI 進行界面更新搬卒。

在前面講表達式的時候已經(jīng)講過集合在布局中的使用(可以使用[]運算符訪問集合)瑟俭,這里不再重復(fù)講解。

可觀察的對象

實現(xiàn) Observable接口的類契邀,它就是一個可觀察的類摆寄,允許希望被通知的對象注冊數(shù)據(jù)更改的監(jiān)聽器。

這個 Observable 接口具有添加和刪除監(jiān)聽器的機制坯门,但必須由你來決定什么時候發(fā)送通知微饥。為了更方便的開發(fā),Data Binding 提供了實現(xiàn)監(jiān)聽器注冊機制的類 BaseObservable古戴。當(dāng)你自定義的類繼承了數(shù)據(jù)類 BaseObservable 時欠橘,需要通過 @Bindable 注解標(biāo)記 getter 方法為一個可觀察的屬性,然后通過notifyPropertyChanged() 方法來通知數(shù)據(jù)發(fā)生改變(通常是在 setter 方法中調(diào)用)现恼,如下所示:

package com.example.databindingdemo.bean;

import android.databinding.BaseObservable;
import android.databinding.Bindable;

import com.example.databindingdemo.BR;


/**
 * @author yanglijun
 * @date 19-2-22
 */
public class CelebrityInfo extends BaseObservable {
    private String name;
    private int weight;
    private int photo;
    private boolean isRetire;
    private double income;

    @Bindable
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        notifyPropertyChanged(BR.name);
    }

    @Bindable
    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
        notifyPropertyChanged(BR.weight);
    }

    @Bindable
    public int getPhoto() {
        return photo;
    }

    public void setPhoto(int photo) {
        this.photo = photo;
        notifyPropertyChanged(BR.photo);
    }

    @Bindable
    public boolean isRetire() {
        return isRetire;
    }

    public void setRetire(boolean retire) {
        isRetire = retire;
        notifyPropertyChanged(BR.retire);
    }

    @Bindable
    public double getIncome() {
        return income;
    }

    public void setIncome(double income) {
        this.income = income;
        notifyPropertyChanged(BR.income);
    }

    public void copyObj(CelebrityInfo info){
        this.name = info.getName();
        this.income = info.getIncome();
        this.isRetire = info.isRetire();
        this.photo = info.getPhoto();
        this.weight = info.getWeight();
        notifyPropertyChanged(BR._all);
    }
}

這里的所有 getter 方法上都有一個 @Binding 注解肃续,所有的 setter 方法中都有一個 notifyPropertyChanged(BR.xxx) 方法黍檩,這兩個得成對使用才能達到數(shù)據(jù)改變則自動刷新的功能。其中 BR.xxx 是你在 getter 方法上增加注解后編譯器自動生成的始锚,它類似于 Android 的 R 文件刽酱,它里面創(chuàng)建了一系列綁定的 ID,生成規(guī)則是根據(jù) getter 方法名而定的(去掉 get瞧捌,is棵里,按駝峰規(guī)則命名)。

setter 方法中調(diào)用 notifyPropertyChanged(BR.xxx) 方法是通知這單個屬性的數(shù)據(jù)變化姐呐,如果你想一次性通知所有字段的觀察者刷新數(shù)據(jù)則可以調(diào)用 notifyPropertyChanged(BR._all) 方法殿怜,BR._all 是默認(rèn)生成的 ID,使用它可以通知對象中所有帶 @Binding 注解的方法數(shù)據(jù)改變曙砂。比如:

public class CelebrityInfo extends BaseObservable {
    ...
    public void copyObj(CelebrityInfo info){
        this.name = info.getName();
        this.income = info.getIncome();
        this.isRetire = info.isRetire();
        this.photo = info.getPhoto();
        this.weight = info.getWeight();
        notifyPropertyChanged(BR._all);
    }
}

此篇到這里就結(jié)束了稳捆,可以查看下一篇 Data Binding 詳解(四)-生成的綁定類

如果你覺得文章有幫助到你麦轰,記得點個喜歡以表支持乔夯,同時歡迎你的指正和建議。十分感謝款侵!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末末荐,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子新锈,更是在濱河造成了極大的恐慌甲脏,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件妹笆,死亡現(xiàn)場離奇詭異块请,居然都是意外死亡,警方通過查閱死者的電腦和手機拳缠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進店門墩新,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人窟坐,你說我怎么就攤上這事海渊。” “怎么了哲鸳?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵臣疑,是天一觀的道長。 經(jīng)常有香客問我徙菠,道長讯沈,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任婿奔,我火速辦了婚禮缺狠,結(jié)果婚禮上问慎,老公的妹妹穿的比我還像新娘。我一直安慰自己儒老,他們只是感情好蝴乔,可當(dāng)我...
    茶點故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布记餐。 她就那樣靜靜地躺著驮樊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪片酝。 梳的紋絲不亂的頭發(fā)上囚衔,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天,我揣著相機與錄音雕沿,去河邊找鬼练湿。 笑死,一個胖子當(dāng)著我的面吹牛审轮,可吹牛的內(nèi)容都是我干的肥哎。 我是一名探鬼主播,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼疾渣,長吁一口氣:“原來是場噩夢啊……” “哼篡诽!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起榴捡,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤杈女,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后吊圾,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體达椰,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年项乒,在試婚紗的時候發(fā)現(xiàn)自己被綠了啰劲。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡檀何,死狀恐怖呈枉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情埃碱,我是刑警寧澤猖辫,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站砚殿,受9級特大地震影響啃憎,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜似炎,卻給世界環(huán)境...
    茶點故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一辛萍、第九天 我趴在偏房一處隱蔽的房頂上張望悯姊。 院中可真熱鬧,春花似錦贩毕、人聲如沸悯许。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽先壕。三九已至,卻和暖如春谆甜,著一層夾襖步出監(jiān)牢的瞬間垃僚,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工规辱, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留谆棺,地道東北人。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓罕袋,卻偏偏與公主長得像改淑,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子浴讯,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,691評論 2 361