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類中實作
至此,更新過程完畢。
整個注冊與更新過程可以用一張流程圖來概括:
事件處理的原理很簡單,在生成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綁定就結束了。