天天看點

Android的DataBinding原理介紹

activity在inflate layout時,通過databindingutil來生成綁定,從代碼看,是周遊contentview得到view數組對象,然後通過資料綁定library生成對應的binding類,含views、變量、listeners等。生成類位于

首先,會在父類(viewdatabinding)中執行個體化回調或handler,用于之後的綁定操作;

接着,通過調用 mapbindings(…) 周遊布局以獲得包含bound、includes、id views的數組對象,再依次賦給對應view

然後,調用 invalidateall() -> requestrebind() -> … -> mrebindrunnable.run() – 執行 runnable

最後,通過該runnable會執行到 executependingbindings() -> … -> executebindings(),在這裡會執行綁定相關操作。

首先,通過mdirtyflags辨別變量(所有變量共用)

然後,調用 notifypropertychanged(…) 來通知更新(若有回調)

最後,調用 requestrebind() -> … -> executebindings() 再次執行綁定操作,将資料更新到views上

observable 對象

在設定變量時,會先調用 updateregistration(..) 注冊一個observable對象的監聽

observablefields 對象

與 observable 對象不同的是,observable對象的監聽是在 executebindings() 中注冊的

入口 updateregistration(0, contact) :

每個observable對象都會添加一個觀察監聽,儲存在數組 mlocalfieldobservers 中,并以 localfieldid 索引。

create_property_listener 為何物?

create_property_listener 實際上隻是一個接口執行個體,注冊時會調用它的create()方法建立一個弱引用listener,它的作用是将listener綁定到observable對象上,

綁定時,會調用 listener.settarget(…) 将observable對象傳給 weakpropertylistener執行個體,然後,weakpropertylistener 會為 observable對象添加onpropertychangedcallback。

addonpropertychangedcallback實作

addonpropertychangedcallback 在 baseobservable中實作,首先會執行個體化一個propertychangeregistry對象,同時建立一個用來通知observable對象重新綁定更新的回調callbackregistry.notifiercallback。然後将 onpropertychangedcallback 添加到propertychangeregistry的回調清單中

這樣,注冊observable對象的監聽就完畢了。

設定或更新observable對象時都會調用notifypropertychanged()或notifychange()來通知更新,那到底是如何更新的呢?

回調過程

通過 notifypropertychanged 調用到 mnotifier 回調, mnotifier 通知onpropertychangedcallback observable對象屬性發生變化,然後在onpropertychanged中又轉給viewdatabinding對象(生成的binding類)處理。

判斷是否需要重新綁定并執行,在生成的binding類中實作

至此,更新過程完畢。

整個注冊與更新過程可以用一張流程圖來概括:

Android的DataBinding原理介紹

事件處理的原理很簡單,在生成binding類中會實作view事件的監聽,在構造時執行個體化view的事件監聽,然後在綁定時将事件監聽對象指派給對應view,這樣,點選時就會觸發相應的監聽。

生成的binding類并實作view的事件監聽

執行個體化view的事件監聽

在執行綁定中綁定view事件監聽

觸發事件并執行

原理類似,隻是利用 viewstubproxy 來延遲綁定。

使用layout中的viewstub執行個體化一個viewstubproxy對象賦給viewstub變量,并與bingding關聯

執行個體化viewstubproxy的同時會注冊inflate監聽

inflate viewstub

當viewstub infate時,執行mproxylistener,其中會生成viewstub的binding,并強制執行主binding重綁

綁定viewstub

這樣,viewstub綁定就結束了。

繼續閱讀