DataBinding其三

  1. 雙向綁定
  2. DataBinding剩下的注解

很快啊辕漂,就來到了DataBinding的第三篇。在這里將介紹DataBinding中高級的知識點(diǎn)(自認(rèn)為高級)通砍,下面就來瞧瞧這些高級的知識點(diǎn)。

1、雙向綁定

其實(shí)早該在介紹綁定表達(dá)式的時候應(yīng)該要介紹雙向綁定的了彻亲,但是為了雙向綁定完整,所以就留到了這吮廉,所謂雙向綁定是這樣的:

我們可以單向綁定數(shù)據(jù)和一些監(jiān)聽器(事件)苞尝。在更新數(shù)據(jù)的時候,綁定了的控件就會更新宦芦,而監(jiān)聽器發(fā)生改變的時候宙址,我們就更新綁定的數(shù)據(jù)。

這就是雙向綁定的原理调卑。

而DataBinding給我們提供了雙向綁定的基本實(shí)現(xiàn)以及自定義抡砂。

1.1、可觀察數(shù)據(jù)類型

并不是所有的數(shù)據(jù)類型都可以進(jìn)行雙向綁定恬涧,DataBinding給我們提供了一些:

可觀察數(shù)據(jù)類型

大概是這么多注益。

而使用雙向綁定的表達(dá)式也和普通綁定表達(dá)式有那么一點(diǎn)點(diǎn)不一樣:

@={}這就是雙向綁定表達(dá)式,比普通綁定表達(dá)式多了一個等號=气破。

最常用到雙向表達(dá)式的莫過于EditText控件了聊浅,當(dāng)輸入內(nèi)容時,更新綁定的數(shù)據(jù)现使,但改變數(shù)據(jù)時低匙,更新EditText控件的顯示。

1.2碳锈、雙向綁定特性

也并不是所有的屬性都支持雙向綁定顽冶,至于哪些屬性(特性)可以進(jìn)行雙向綁定,官方也列出了一個表格:

雙向數(shù)據(jù)綁定特性

1.3售碳、自定義可觀察數(shù)據(jù)類型(@Bindable)

如果DataBinding提供的可觀察數(shù)據(jù)類型都不能夠滿足你的業(yè)務(wù)强重,那么還是可以自定義的。
新建一個類贸人,繼承BaseObservable间景,并創(chuàng)建一個屬性,給這個屬性加上@Bindable注解艺智,然后重寫該屬性set方法即可倘要,大概是這樣的:

class Demo : BaseObservable() {
    @Bindable
    var name: String = ""
        set(value) {
            field = value
            notifyPropertyChanged(BR.name)
        }
}

@Bindable注解:該注解主要作用于get方法或者是字段本身,作用是生成一個BR值供notifyPropertyChanged方法調(diào)用以更新數(shù)據(jù)十拣。

這時我們就可以對name這個屬性進(jìn)行雙向綁定了:

<EditText
    android:text=“@={demo.name}”/>

但是你實(shí)際運(yùn)行你會發(fā)現(xiàn)它報(bào)錯了封拧,報(bào)錯的原因是類型不匹配志鹃。這時候該怎么辦呢?

1.4泽西、雙向數(shù)據(jù)轉(zhuǎn)換(@InverseMethod)

Databinding提供了數(shù)據(jù)轉(zhuǎn)換的方案曹铃,單向和雙向都有,我們先來說雙向的捧杉。

定義一個靜態(tài)類陕见,提供兩個方法。一個充當(dāng)正向數(shù)據(jù)轉(zhuǎn)換器味抖,另外一個充當(dāng)反向數(shù)據(jù)轉(zhuǎn)換器淳玩,大概是這樣的:

object Canversion{
    @InverseMethod("chToString")
    fun stringToCh(value: String): CharSequence {
          return value
    }

    fun chToString(value: CharSequence): String {
          return value.toString()
    }
}

事實(shí)上,兩個頂級函數(shù)也是可以的非竿。

InverseMethod注解:該注解修飾的就是正向轉(zhuǎn)換器,而InverseMethod接收一個參數(shù)谋竖,就是反向數(shù)據(jù)轉(zhuǎn)換器的名稱红柱。

還記得<import>標(biāo)簽嗎,當(dāng)轉(zhuǎn)換器定義好之后蓖乘,我們就可以通過該標(biāo)簽將這個類導(dǎo)入到xml中锤悄,然后使用正向轉(zhuǎn)換器就可以了:

<import type=“…Conversion”/>

<EditText
    android:text=“@={Conversion.stringToCh(demo.name)}”/>

1.5、自定義雙向綁定(InverseBindingAdapter)

如果DataBinding默認(rèn)實(shí)現(xiàn)的雙向綁定特性也不能滿足需求的時候嘉抒,就只能自定義了零聚。
事實(shí)上,雙向綁定就由兩個單向綁定(數(shù)據(jù)綁定和監(jiān)聽器綁定)組成的些侍,所以第一步就是建立兩個單向綁定隶症。下面重新實(shí)現(xiàn)android:text的雙向綁定。
首先創(chuàng)建一個數(shù)據(jù)綁定

@BindingAdapter("app:test")
fun test(view: TextView, text: CharSequence?) {
    val oldText = view.text
    if (text == oldText || (oldText.isNullOrEmpty())) {
        return
    }
    if (text is Spanned) {
        if (text == oldText) {
            return; // No change in the spans, so don't set anything.
        }
    } else if (!haveContentsChanged(text, oldText)) {
        return; // No content changes, so don't set anything.
    }
    view.text = text
}

在賦值之前需要對數(shù)據(jù)進(jìn)行判斷:
只有是更新的數(shù)據(jù)才可以被賦值岗宣。防止無限循環(huán)的發(fā)生蚂会。

然后,創(chuàng)建一個事件監(jiān)聽綁定

@BindingAdapter("app:testAttrChanged")
fun setTextWatcher(view: TextView, textAttrChanged: InverseBindingListener?) {
    val newValue: TextWatcher? = if (textAttrChanged == null) {
        null
    } else {
        object : TextWatcher {
            //code..
            override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
                textAttrChanged.onChange()
            }
            //code..
        }
    }
    if (newValue != null) {
        view.addTextChangedListener(newValue)
    }
}

這是一個事件監(jiān)聽耗式,當(dāng)EditText發(fā)生改變的時候胁住,就會通過InverseBindingListener對象通知更改。

最后刊咳,將這兩個綁定關(guān)聯(lián)在一起:

@InverseBindingAdapter(attribute = "app:test", event = "app:testAttrChanged")
fun getTextString(view: TextView): CharSequence {
    return view.text // 返回控件的值
}

InverseBindingAdapter注解:該注解主要有兩個參數(shù)彪见,attribute指定數(shù)據(jù)綁定的名稱,event指定事件綁定的名稱娱挨。作用是將兩者結(jié)合起來形成雙向綁定余指,并且響應(yīng)事件綁定,在事件發(fā)生時返回控件的值让蕾。

通過這三步浪规,自定義雙向綁定的屬性就完成了:

<EditText
    app:test=“@={demo.name}”/>

自定義雙向綁定的一個細(xì)節(jié):
在自定義雙向綁定中或听,對于app:testAttrChanged是可以識別的,規(guī)律就是:


數(shù)據(jù)綁定名稱+AttrChanged笋婿。

所以在關(guān)聯(lián)的時候event可以省略不寫誉裆。

1.6、簡化自定義雙向綁定(InverseBindingMethods和InverseBindingMethod)

有沒有更加簡單的方式實(shí)現(xiàn)雙向綁定呢缸濒?答案是沒有的W愣!雙向綁定就必須是一個數(shù)據(jù)綁定加上一個事件綁定庇配。這是永遠(yuǎn)都沒辦法省略的斩跌。但是如果你有多個雙向綁定需要實(shí)現(xiàn),那么可以簡化的只有InverseBindingAdapter注解修飾的方法了捞慌。

首先定義一個類:

@InverseBindingMethods(
    InverseBindingMethod(
        type = TextView::class,
        attribute = "app:test",
        method = "getText"
    )
)
object BindingAdapterImpl

InverseBindingMethods:該注解接收的參數(shù)是InverseBindingMethod數(shù)組耀鸦。
而一個InverseBindingMethod對應(yīng)的就是一個InverseBindingAdapter,下面我們來分析一下InverseBindingMethod

也就是說InverseBindingMethodsInverseBindingMethod的作用就是批量的InverseBindingAdapter啸澡。

InverseBindingMethod該注解有四個參數(shù):

type:是一個class對象袖订,指定雙向綁定的控件,比如TextView

attribute:和InverseBindingAdapter中同名的參數(shù)作用一樣嗅虏,指定數(shù)據(jù)綁定的方法洛姑。

event:和InverseBindingAdapter中同名的參數(shù)作用一樣,指定事件綁定的方法皮服。(可以看出楞艾,上面的例子我沒有寫該屬性,是因?yàn)榭梢宰詣油茰y)

method:指定控件提供數(shù)據(jù)的方法龄广。(事實(shí)上該參數(shù)也可以不寫硫眯,當(dāng)控件存在與attribute同名的get方法時,也就是說如果TextView中存在一個getTest方法蜀细,那么這個參數(shù)就可以缺手弁)

需要注意的是:這兩個注解替代的是InverseBindingAdapter,所以數(shù)據(jù)綁定和事件綁定依舊需要實(shí)現(xiàn)奠衔。

一句話概括:

當(dāng)可觀察數(shù)據(jù)對象更改時谆刨,通過attribute指定的方法更新type的對象,當(dāng)event事件發(fā)生時归斤,將從method方法中獲得數(shù)據(jù)返回給可觀察數(shù)據(jù)對象痊夭。

2、DataBinding剩下的注解

終于說完雙向綁定了脏里,在說明雙向綁定的時候也將和雙向綁定有關(guān)的注解說了一下她我,接下來就說說DataBinding剩下的注解。

2.1、單向數(shù)據(jù)轉(zhuǎn)換(BindingConversion)

上面提到數(shù)據(jù)轉(zhuǎn)換有兩種番舆,雙向的已經(jīng)介紹了酝碳,現(xiàn)在來看單向的數(shù)據(jù)轉(zhuǎn)換:

@BindingConversion
fun dateToString(time: Date): String{
    return SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(time)
}

將Date類型轉(zhuǎn)換成String類型輸出。

<TextView
      android:text=“@{date}”/>//date是一個Date類型的對象

注意:

單向數(shù)據(jù)轉(zhuǎn)換只需要輸入(參數(shù)列表)輸出(返回值)對上即可自動使用恨狈,無需手動調(diào)用疏哗。

再次注意:所有的數(shù)據(jù)轉(zhuǎn)換都只能一對一。

2.2禾怠、簡化單向綁定(BindingMethods和BindingMethod)

@BindingMethods({
        @BindingMethod(type = TextView.class, attribute = "android:autoLink", method = "setAutoLinkMask")
})

和雙向綁定的差不多返奉,BindingMethods接收的也是BindingMethod的數(shù)組。
來看看BindingMethod注解:

@BindingMethod注解有三個變量:
type:指定單向綁定的控件吗氏,比如:TextView
attribute:指定單向綁定的名稱
method:指定響應(yīng)單向綁定的set方法

BindingMethodsBindingMethod相當(dāng)于批量的BindingAdapter芽偏。

一句話概括:
attribute屬性實(shí)現(xiàn)單向綁定,通過method方法將值設(shè)置給type類型的控件弦讽。

總結(jié)

最后一篇介紹了dataBinding的雙向綁定和剩下的注解污尉,到此Databinding算是基本講完了。DataBinding主要分為三部分:xml部分往产,activity/fragment部分以及自定義綁定(單向綁定和雙向綁定)部分十厢。


到后面你會發(fā)現(xiàn),xml之所以可以使用綁定表達(dá)式捂齐,是因?yàn)锧BindingAdapter標(biāo)簽。當(dāng)然了缩抡,這只是DataBinding的使用奠宜,真正的實(shí)現(xiàn):為什么@BindingAdapter這么神奇,其背后的原理才是DataBinding真正的核心瞻想。這就是注解部分的內(nèi)容了压真。對于日常開發(fā)來說,學(xué)完DataBinding的這幾個注解就已經(jīng)足夠了蘑险。

對于學(xué)習(xí)滴肿,最重要的是要去寫,只有真正寫過佃迄,實(shí)現(xiàn)了泼差,才能算掌握了。

因?yàn)檎胬矶际窃趯?shí)踐當(dāng)中呵俏。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末堆缘,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子普碎,更是在濱河造成了極大的恐慌吼肥,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異缀皱,居然都是意外死亡斗这,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進(jìn)店門啤斗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來表箭,“玉大人,你說我怎么就攤上這事争占∪悸撸” “怎么了?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵臂痕,是天一觀的道長伯襟。 經(jīng)常有香客問我,道長握童,這世上最難降的妖魔是什么姆怪? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮澡绩,結(jié)果婚禮上稽揭,老公的妹妹穿的比我還像新娘。我一直安慰自己肥卡,他們只是感情好溪掀,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著步鉴,像睡著了一般揪胃。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上氛琢,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天喊递,我揣著相機(jī)與錄音,去河邊找鬼阳似。 笑死骚勘,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的撮奏。 我是一名探鬼主播俏讹,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼畜吊!你這毒婦竟也來了藐石?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤定拟,失蹤者是張志新(化名)和其女友劉穎于微,沒想到半個月后逗嫡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡株依,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年驱证,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片恋腕。...
    茶點(diǎn)故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡抹锄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出荠藤,到底是詐尸還是另有隱情伙单,我是刑警寧澤,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布哈肖,位于F島的核電站吻育,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏淤井。R本人自食惡果不足惜布疼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望币狠。 院中可真熱鬧游两,春花似錦、人聲如沸漩绵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽止吐。三九已至轰坊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間祟印,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工粟害, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蕴忆,地道東北人。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓悲幅,卻偏偏與公主長得像套鹅,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子汰具,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評論 2 353

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