Android中的DataBinding的原理淺析

一、什么是DataBinding

知道DataBinding的應該也會知道MVVM設計模式昌粤,該模式實現(xiàn)了View與Model的雙向綁定從而實現(xiàn)了View和Model的同步更新熔萧。MVVM是一種架構思想而DataBinding就是實現(xiàn)這一思想的工具磷箕。

二尝江、DataBinding的使用

我們要對DataBinding進行原理分析前吠昭,首先要會使用DataBinding傲隶。
在build.gradel中配置DataBinding

android {
    ...
    dataBinding{
        enabled true
    }
}

對View的布局文件進行配置饺律,使用layout作為跟布局標簽。使用data標簽進行DataBinding的綁定跺株「幢簦控件中可以使用@{}進行綁定脖卖,@{}為單向綁定@={}為雙向綁定

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <!--DataBinding的配置文件-->
    <data>
        <!--name屬性相當于聲明了一個全局屬性、type指定name對應的具體的數(shù)據(jù)類或是MVVM中VM-->
        <variable
                name="userInfo"
                type="com.scjd.framemodel_databinding.UserInfo"/>
    </data>
    <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent"
                  android:padding="50dp"
                  android:orientation="vertical">
        <EditText android:layout_width="match_parent" android:layout_height="wrap_content"
                  android:text="@={userInfo.userName}"/>
        <EditText android:layout_width="match_parent" android:layout_height="wrap_content"
                  android:text="@{userInfo.passWord}"/>
        <View android:layout_width="wrap_content" android:layout_height="wrap_content"/>
    </LinearLayout>
</layout>

聲明一個數(shù)據(jù)類巧颈,使用ObservableField聲明屬性并通過范型指定數(shù)據(jù)類型畦木。

public class UserInfo {
    public ObservableField<String> userName = new ObservableField<>();
    public ObservableField<String> passWord = new ObservableField<>();
}

在Activity中進行綁定

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        var binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        var userInfo = UserInfo()
        userInfo.userName.set("xixi")
        userInfo.passWord.set("123")
        binding.userInfo = userInfo
    }
}

以上就是一個通過DataBinding實現(xiàn)雙向綁定的例子。

三砸泛、Data Binding的原理分析

我們通過上面的例子對DataBinding進行原理分析十籍。首先我們要知道DataBinding使用了apt技術,我們build項目時DataBinding會生成多個文件唇礁,我們可以在build文件中查看

圖片.png
圖片.png

DataBinding還將原有的activity_main.xml文件進行了拆分勾栗,分別是activity_mian.xml和activity_main-layout.xml。

activity_main.xml

通過上面的代碼我們發(fā)現(xiàn)DataBinding將原有的layout和data標簽去除了盏筐。并為根布局聲明了一個layout/文件名_0的tag围俘,為其他使用到@{}或@={}的控件按順序添加了一個binding_X的tag。

activity_main-layout.xml

該配置文件中詳細的記述了<Variables declared="true" type="com.scjd.framemodel_databinding.UserInfo" name="userInfo"> 我們聲明的全局變量琢融,變量指向的數(shù)據(jù)類型的絕對路徑界牡。<Target tag="binding_1" view="EditText">tag對應的View類型。<Expression text="userInfo.userName" attribute="android:text">控件綁定具體屬性和Model中的具體屬性漾抬。<TwoWay>true</TwoWay>是否是雙向的宿亡。

接下來我們通過Activity中的 var binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)進行入手

方法中通過activity的setContentView加載布局,并通過window找到id為content的ViewGroup奋蔚,它是一個FrameLayout用于加載我們添加的布局文件她混。接下來就是bindToAddedViews方法。

parent中的子View就是我們布局文件中的根布局LinearLayout泊碑,所以走的是if中的代碼

bind方法又調用了DataBinderMapperImpl中的getDataBinder方法士嚎。

通過一系列的條件判斷之后返回了一個ActivityMainBindingImpl對象八千,接下來我們看它的構造方法。

上面的代碼看著非常的多,但是它就是將布局中的含有databinding賦值的tag控件一一存入bindings的Object的數(shù)組中并返回惧眠。

該方法中將獲取的View數(shù)組賦值給成員變量,接下來看invalidateAll()方法猖败。

上面代碼調用過來就是為了執(zhí)行mRebindRunnable没隘。在看該Runnable中的executePendingBindings()方法

上面也是對一些狀態(tài)進行了判斷添加一下回調,主要的還是executeBindings()方法窘奏。

看了上面的方法是不是有一種終于熬到頭的感覺了呢嘹锁,當((dirtyFlags & 0xeL) != 0)或((dirtyFlags & 0xdL) != 0)成立時就會把Model中的數(shù)據(jù)set到相應的View中,這個就是單向的M->V着裹。((dirtyFlags & 0x8L) != 0)成立時就是V->M它為雙向綁定的控件添加了一個內容變化的監(jiān)聽mboundView1androidTextAttrChanged

當控件中的內容發(fā)生變化時领猾,就會更新到Model上。

activity中為userInfo賦的值就是上面的mUserInfo。
通過上面的代碼我們對DataBinding的綁定過程又了一定的了解摔竿,但是還有兩個問題我們沒有解決面粮,那就是View和Model的變化有時在哪里監(jiān)聽的呢。

還記得上面的mRebindRunnable嗎继低?通過對它的查找我們在ViewDataBinding的靜態(tài)代碼塊中發(fā)現(xiàn)了端倪熬苍。

看到上面的代碼是不是一下就明白了V的變化監(jiān)聽了呢。

DataBinding通過布局中的tag將控件查找出來袁翁,然后根據(jù)生成的配置文件將V與M進行對應的同步操作柴底,設置一個全局的布局變化監(jiān)聽來實時更新,M通過他的set方法進行同步梦裂。

該文檔是自己的學習記錄如有錯誤歡迎指出似枕。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市年柠,隨后出現(xiàn)的幾起案子凿歼,更是在濱河造成了極大的恐慌,老刑警劉巖冗恨,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件答憔,死亡現(xiàn)場離奇詭異,居然都是意外死亡掀抹,警方通過查閱死者的電腦和手機虐拓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來傲武,“玉大人蓉驹,你說我怎么就攤上這事【纠” “怎么了态兴?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長疟位。 經(jīng)常有香客問我瞻润,道長,這世上最難降的妖魔是什么甜刻? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任绍撞,我火速辦了婚禮,結果婚禮上得院,老公的妹妹穿的比我還像新娘傻铣。我一直安慰自己,他們只是感情好祥绞,可當我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布矾柜。 她就那樣靜靜地躺著阱驾,像睡著了一般就谜。 火紅的嫁衣襯著肌膚如雪怪蔑。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天丧荐,我揣著相機與錄音缆瓣,去河邊找鬼。 笑死虹统,一個胖子當著我的面吹牛弓坞,可吹牛的內容都是我干的。 我是一名探鬼主播车荔,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼渡冻,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了忧便?” 一聲冷哼從身側響起族吻,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎珠增,沒想到半個月后超歌,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡蒂教,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年巍举,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凝垛。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡懊悯,死狀恐怖,靈堂內的尸體忽然破棺而出梦皮,到底是詐尸還是另有隱情炭分,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布届氢,位于F島的核電站欠窒,受9級特大地震影響,放射性物質發(fā)生泄漏退子。R本人自食惡果不足惜岖妄,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望寂祥。 院中可真熱鬧荐虐,春花似錦、人聲如沸丸凭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至铛碑,卻和暖如春狠裹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背汽烦。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工涛菠, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人撇吞。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓俗冻,卻偏偏與公主長得像,于是被迫代替她去往敵國和親牍颈。 傳聞我的和親對象是個殘疾皇子迄薄,可洞房花燭夜當晚...
    茶點故事閱讀 44,927評論 2 355