在前兩篇文章中咱們結合源碼學習了Module、Component的註冊、調用、回調等流程,相信你們必定收穫頗多,對Weex的理解也必定越發深刻。git
那麼本篇文章咱們分析Weex的渲染流程,來看一看咱們寫的Js文件是如何在Native端變成Android裏View的。github
在Activity中咱們開個某個Weex頁面使用的是WXSDKInstance中的render方法,最終也是按照常規套路經過WXBridge調用Js繼續處理。bash
備註:Js引擎處理後回調Native這一部分要複雜的多,咱們拆分紅幾步來看。微信
從上咱們能夠看出真實的渲染過程由WXDomHandler發起,關鍵方法在DOMActionContextImpl和WXComponent中(標出關鍵方法的地方);也經歷了測量、佈局、繪製、處理事件、設置數據等流程。app
渲染流程很是重要,裏面有不少關鍵步驟,下面咱們一一分析;dom
calculateLayout分析:源碼分析
/**
* create view
*/
public final void createView() {
mHost = initComponentHostView(mContext);
if (mHost == null && !isVirtualComponent()) {
//compatible
initView();
}
if(mHost != null){
mHost.setId(WXViewUtils.generateViewId());
ComponentObserver observer;
if ((observer = getInstance().getComponentObserver()) != null) {
observer.onViewCreated(this, mHost);
}
}
onHostViewInitialized(mHost);
}
複製代碼
createView分析:佈局
/**
* layout view
*/
public final void setLayout(ImmutableDomObject domObject) {
......
Spacing parentPadding = (nullParent?new Spacing():mParent.getDomObject().getPadding());
Spacing parentBorder = (nullParent?new Spacing():mParent.getDomObject().getBorder());
Spacing margin = mDomObj.getMargin();
int realWidth = (int) mDomObj.getLayoutWidth();
int realHeight = (int) mDomObj.getLayoutHeight();
int realLeft = (int) (mDomObj.getLayoutX() - parentPadding.get(Spacing.LEFT) -
parentBorder.get(Spacing.LEFT));
int realTop = (int) (mDomObj.getLayoutY() - parentPadding.get(Spacing.TOP) -
parentBorder.get(Spacing.TOP)) + siblingOffset;
int realRight = (int) margin.get(Spacing.RIGHT);
int realBottom = (int) margin.get(Spacing.BOTTOM);
......
mAbsoluteY = (int) (nullParent?0:mParent.getAbsoluteY() + mDomObj.getLayoutY());
mAbsoluteX = (int) (nullParent?0:mParent.getAbsoluteX() + mDomObj.getLayoutX());
......
setComponentLayoutParams(realWidth, realHeight, realLeft, realTop, realRight, realBottom, rawOffset);
......
}
複製代碼
setLayout分析:學習
public void addEvent(String type) {
......
View view = getRealView();
if (type.equals(Constants.Event.CLICK) && view != null) {
addClickListener(mClickEventListener);
} else if ((type.equals(Constants.Event.FOCUS) || type.equals(Constants.Event.BLUR))) {
addFocusChangeListener(new WXComponent.OnFocusChangeListener() {
public void onFocusChange(boolean hasFocus) {
Map<String, Object> params = new HashMap<>();
params.put("timeStamp", System.currentTimeMillis());
fireEvent(hasFocus ? Constants.Event.FOCUS : Constants.Event.BLUR, params);
}
});
} else if (view != null &&
needGestureDetector(type)) {
if (view instanceof WXGestureObservable) {
if (mGesture == null) {
mGesture = new WXGesture(this, mContext);
boolean isPreventMove = WXUtils.getBoolean(getDomObject().getAttrs().get(Constants.Name.PREVENT_MOVE_EVENT), false);
mGesture.setPreventMoveEvent(isPreventMove);
}
mGestureType.add(type);
((WXGestureObservable) view).registerGestureListener(mGesture);
} else {
WXLogUtils.e(view.getClass().getSimpleName() + " don't implement " +
"WXGestureObservable, so no gesture is supported.");
}
} else {
Scrollable scroller = getParentScroller();
if (type.equals(Constants.Event.APPEAR) && scroller != null) {
scroller.bindAppearEvent(this);
}
if (type.equals(Constants.Event.DISAPPEAR) && scroller != null) {
scroller.bindDisappearEvent(this);
}
}
}
複製代碼
addEvents分析:ui
bindData:
總結:
下面咱們對Weex的渲染和Android的渲染流程進行一下對比:
歡迎持續關注Weex源碼分析項目:Weex-Analysis-Project
歡迎關注微信公衆號:按期分享Java、Android乾貨!