Weex Android SDK源码分析之界面渲染(下)
来源:互联网 发布:苹果电脑做java开发 编辑:程序博客网 时间:2024/04/29 08:54
前言
在你读本篇文章之前请确认您已经阅读 Weex Android SDK源码分析之界面渲染(上),否则建议您先阅读上篇文章有利于您更深刻的了解~
流程图
源码分析
回忆一下上篇文章的讲解,最终由WxBridgeManage调用WxBridge调用了so中native代码进行JS代码解析,那么解析完成之后是如何返回给Android代码的呢?so返回的是什么数据呢?数据时如何转换的呢?数据与最终的UI有什么关系呢?最终是如何转换成view的呢?如何传递到activity中的呢?
带着这些的疑问,我们开始今天得讲解~
一、WXBridge —> 解析JS回调Android code
/** * Js 使用此方法回调Android代码 * @param instanceId * @param tasks 任务 * @param callback 下一个任务的ID */ public void callNative(String instanceId, String tasks, String callback) { WXBridgeManager.getInstance().callNative(instanceId, tasks, callback); }
二、WXBridgeManager — > 分配渲染任务
/** * Dispatch the native task to be executed. * * @param instanceId {@link WXSDKInstance#mInstanceId} * @param tasks tasks to be executed * @param callback next tick id 下一个挂钩子ID,so执行需要的 */ void callNative(String instanceId, String tasks, String callback) { if (TextUtils.isEmpty(tasks)) { return; } if (WXEnvironment.isApkDebugable()) { mLodBuilder.append("[WXBridgeManager] callNative >>>> instanceId:").append(instanceId) .append(", tasks:") .append(tasks).append(", callback:").append(callback); WXLogUtils.d(mLodBuilder.substring(0)); mLodBuilder.setLength(0); } JSONArray array = JSON.parseArray(tasks); int size = array.size(); if (size > 0) { try { JSONObject task; for (int i = 0; i < size; ++i) { task = (JSONObject) array.get(i); if (task != null && WXSDKManager.getInstance() .getSDKInstance(instanceId) != null) { WXModuleManager .callModuleMethod(instanceId, (String) task.get("module") , (String) task.get("method") ,(JSONArray) task.get("args")); } } } catch (Exception e) { } } if (UNDEFINED.equals(callback) || mDestroyedInstanceId.equals(instanceId)) { return; } // get next tick getNextTick(instanceId, callback); } // 获取下一个需要渲染的JS数据 private void getNextTick(final String instanceId, final String callback) { addNextTickTask(instanceId, callback, "{}"); sendMessage(instanceId, WXJSBridgeMsgType.CALL_JS_BATCH); } // 添加渲染数据 private void addNextTickTask(String instanceId, Object... args) { if (args == null || args.length == 0) { return; } ArrayList<Object> argsList = new ArrayList<>(); for (Object arg : args) { argsList.add(arg); } WXHashMap<String, Object> task = new WXHashMap<>(); task.put(WXConst.KEY_METHOD, METHOD_CALLBACK); task.put(WXConst.KEY_ARGS, args); if (mNextTickTasks.get(instanceId) == null) { ArrayList<WXHashMap<String, Object>> list = new ArrayList<WXHashMap<String, Object>>(); list.add(task); mNextTickTasks.put(instanceId, list); } else { mNextTickTasks.get(instanceId).add(task); } }
三、WXModuleManager —> 回调module方法
// 执行module中的方法static boolean callModuleMethod(String instanceId, String moduleStr , String methodStr, JSONArray args) { final WXModule wxModule = findModule(instanceId, moduleStr, methodStr); if (wxModule == null) { return false; } wxModule.mWXSDKInstance = WXSDKManager.getInstance().getSDKInstance(instanceId); HashMap<String, Method> methodsMap = sGlobalModuleMethodMap.get(wxModule); methodsMap = methodsMap == null ? sInstanceModuleMethodMap.get(wxModule) : methodsMap; if (methodsMap == null) { return false; } final Method moduleMethod = methodsMap.get(methodStr); try { Type[] paramClazzs = moduleMethod.getGenericParameterTypes(); final Object[] params = new Object[paramClazzs.length]; Object value; Type paramClazz; for (int i = 0; i < paramClazzs.length; i++) { paramClazz = paramClazzs[i]; value = args.get(i); if (paramClazz == JSONObject.class) { params[i] = value; } else { String sValue; if (value instanceof String) { sValue = (String) value; } else { sValue = JSON.toJSONString(value); } if (paramClazz == int.class) { params[i] = Integer.parseInt(sValue); } else if (paramClazz == String.class) { params[i] = sValue; } else if (paramClazz == long.class) { params[i] = Long.parseLong(sValue); } else if (paramClazz == double.class) { params[i] = Double.parseDouble(sValue); } else if (paramClazz == float.class) { params[i] = Float.parseFloat(sValue); } else if (ParameterizedType.class. isAssignableFrom(paramClazz.getClass())) { params[i] = JSON.parseObject(sValue, paramClazz); } else if (IWXObject.class.isAssignableFrom(paramClazz.getClass())) { params[i] = JSON.parseObject(sValue, paramClazz); } else { params[i] = JSON.parseObject(sValue, paramClazz); } } } // *** 找到道注解的方法体,进行执行 *** WXModuleAnno anno = moduleMethod.getAnnotation(WXModuleAnno.class); if (anno.runOnUIThread()) { WXSDKManager.getInstance().postOnUiThread(new Runnable() { @Override public void run() { try { // *** 执行module方法 *** moduleMethod.invoke(wxModule, params); } catch (Exception e) { } } }, 0); } else { moduleMethod.invoke(wxModule, params); } } catch (Exception e) { return false; } finally { if (wxModule instanceof WXDomModule) { wxModule.mWXSDKInstance = null; } } return true; } // 找到module 例如 WXDOMModule private static WXModule findModule(String instanceId, String moduleStr, String methodStr) { // find WXModule WXModule wxModule = sGlobalModuleMap.get(moduleStr); Class<? extends WXModule> moduleClass = sModuleClazzMap.get(moduleStr); if (wxModule == null) { HashMap<String, WXModule> moduleMap = sInstanceModuleMap.get(instanceId); if (moduleMap == null) { moduleMap = new HashMap<>(); sInstanceModuleMap.put(instanceId, moduleMap); } // if cannot find the Module, create a new Module and save it wxModule = moduleMap.get(moduleStr); if (wxModule == null) { try { wxModule = moduleClass.getConstructor().newInstance(); } catch (Exception e) { return null; } moduleMap.put(moduleStr, wxModule); // set instance wxModule.mWXSDKInstance = WXSDKManager.getInstance().getSDKInstance(instanceId); } } // find module method HashMap<String, Method> methodsMap = sGlobalModuleMethodMap.get(wxModule); methodsMap = methodsMap == null ? sInstanceModuleMethodMap.get(wxModule) : methodsMap; if (methodsMap == null) { methodsMap = getModuleMethods2Map(moduleClass); sInstanceModuleMethodMap.put(wxModule, methodsMap); } return wxModule; }
四、WXDomModule — > module 方法被触发
public final class WXDomModule extends WXModule { /** * 创建 Body UI * @param element info about how to create a body */ @WXModuleAnno(moduleMethod = true, runOnUIThread = false) public void createBody(JSONObject element) { if (element == null) { return; } Message msg = Message.obtain(); WXDomTask task = new WXDomTask(); task.instanceId = mWXSDKInstance.getInstanceId(); task.args = new ArrayList<>(); task.args.add(element); msg.what = WXDomHandler.MsgType.WX_DOM_CREATE_BODY; msg.obj = task; // *** 发送createBody消息 *** WXSDKManager.getInstance().getWXDomManager().sendMessage(msg); }}
五、WXDomManager —> 发送createBody等消息
// 发送消息 createBody 或者 refresh等public void sendMessage(Message msg) { if (msg == null || mDomHandler == null || mDomThread == null || !mDomThread.isWXThreadAlive() || mDomThread.getLooper() == null) { return; } mDomHandler.sendMessage(msg); }
六、WXDomHandler — > 分发任务类型
// DOM 操作handlerclass WXDomHandler implements Handler.Callback { /** * The batch operation in dom thread will run at most once in 16ms. */ private static final int DELAY_TIME = 16;//ms private WXDomManager mWXDomManager; private boolean mHasBatch = false; public WXDomHandler(WXDomManager domManager) { mWXDomManager = domManager; } @Override public boolean handleMessage(Message msg) { if (msg == null) { return false; } int what = msg.what; Object obj = msg.obj; WXDomTask task = null; if (obj instanceof WXDomTask) { task = (WXDomTask) obj; } if (!mHasBatch) { mHasBatch = true; mWXDomManager. sendEmptyMessageDelayed(WXDomHandler.MsgType.WX_DOM_BATCH, DELAY_TIME); } switch (what) { case MsgType.WX_DOM_CREATE_BODY: // *** createBody *** mWXDomManager.createBody(task.instanceId, (JSONObject) task.args.get(0)); break; case MsgType.WX_DOM_UPDATE_ATTRS: mWXDomManager.updateAttrs(task.instanceId, (String) task.args.get(0), (JSONObject) task.args.get(1)); break; case MsgType.WX_DOM_UPDATE_STYLE: mWXDomManager.updateStyle(task.instanceId, (String) task.args.get(0), (JSONObject) task.args.get(1)); break; case MsgType.WX_DOM_ADD_DOM: mWXDomManager.addDom(task.instanceId, (String) task.args.get(0), (JSONObject) task.args.get(1), (Integer) task.args.get(2)); break; case MsgType.WX_DOM_REMOVE_DOM: mWXDomManager.removeDom(task.instanceId, (String) task.args.get(0)); break; case MsgType.WX_DOM_MOVE_DOM: mWXDomManager.moveDom(task.instanceId, (String) task.args.get(0), (String) task.args.get(1), (Integer) task.args.get(2)); break; case MsgType.WX_DOM_ADD_EVENT: mWXDomManager.addEvent(task.instanceId, (String) task.args.get(0), (String) task.args.get(1)); break; case MsgType.WX_DOM_REMOVE_EVENT: mWXDomManager.removeEvent(task.instanceId, (String) task.args.get(0), (String) task.args.get(1)); break; case MsgType.WX_DOM_CREATE_FINISH: mWXDomManager.createFinish(task.instanceId); break; case MsgType.WX_DOM_REFRESH_FINISH: mWXDomManager.refreshFinish(task.instanceId); break; case MsgType.WX_DOM_BATCH: mWXDomManager.batch(); mHasBatch = false; break; case MsgType.WX_DOM_SCROLLTO: mWXDomManager.scrollToDom(task.instanceId, (String) task.args.get(0), (JSONObject) task.args.get(1)); break; default: break; } return true; } public static class MsgType { public static final int WX_DOM_CREATE_BODY = 0x0; public static final int WX_DOM_UPDATE_ATTRS = 0x01; public static final int WX_DOM_UPDATE_STYLE = 0x02; public static final int WX_DOM_ADD_DOM = 0x03; public static final int WX_DOM_REMOVE_DOM = 0x04; public static final int WX_DOM_MOVE_DOM = 0x05; public static final int WX_DOM_ADD_EVENT = 0x06; public static final int WX_DOM_REMOVE_EVENT = 0x07; public static final int WX_DOM_SCROLLTO = 0x08; public static final int WX_DOM_CREATE_FINISH = 0x09; public static final int WX_DOM_REFRESH_FINISH = 0x0a; public static final int WX_DOM_BATCH = 0xff; }}
七、WXDomManager — > DOM 管理
/** * Invoke {@link WXDomStatement} for creating body according to the JSONObject. * @param instanceId * {@link com.taobao.weex.WXSDKInstance#mInstanceId} for the instance * @param element the jsonObject according to which to create command object. */ void createBody(String instanceId, JSONObject element) { if (!isDomThread()) { throw new WXRuntimeException ("Create body operation must be done in dom thread"); } // *** 调用DOM声明进行元素创建 WXDomStatement statement = new WXDomStatement(instanceId, mWXRenderManager); mDomRegistries.put(instanceId, statement); statement.createBody(element); }
八、WXDomStatement — > DOM声明
/** * 创建根据JSONObject创造体命令对象,并且把命令对象添加到队列. * @param element the jsonObject according to which to create command object. */ void createBody(JSONObject element) { if (mDestroy) { return; } WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(mInstanceId); if (element == null) { if (instance != null) { instance.commitUTStab(WXConst.DOM_MODULE, WXErrorCode.WX_ERR_DOM_CREATEBODY); } return; } WXDomObject domObject = parseInner(element); Map<String, Object> style = new HashMap<>(5); if (domObject.style == null || !domObject.style.containsKey(WXDomPropConstant.WX_FLEXDIRECTION)) { style.put(WXDomPropConstant.WX_FLEXDIRECTION, "column"); } if (domObject.style == null || !domObject.style.containsKey(WXDomPropConstant.WX_BACKGROUNDCOLOR)) { style.put(WXDomPropConstant.WX_BACKGROUNDCOLOR, "#ffffff"); } //If there is height or width in JS, then that value will override value here. if (domObject.style == null || !domObject.style.containsKey(WXDomPropConstant.WX_WIDTH)) { style.put(WXDomPropConstant.WX_WIDTH, WXViewUtils.getWebPxByWidth(WXViewUtils.getWeexWidth(mInstanceId))); } if (domObject.style == null || !domObject.style.containsKey(WXDomPropConstant.WX_HEIGHT)) { style.put(WXDomPropConstant.WX_HEIGHT, WXViewUtils.getWebPxByWidth(WXViewUtils.getWeexHeight(mInstanceId))); } domObject.ref = WXDomObject.ROOT; domObject.updateStyle(style); transformStyle(domObject, true); final WXComponent component = mWXRenderManager.createBodyOnDomThread(mInstanceId, domObject); AddDomInfo addDomInfo = new AddDomInfo(); addDomInfo.component = component; mAddDom.put(domObject.ref, addDomInfo); mNormalTasks.add(new IWXRenderTask() { @Override public void execute() { mWXRenderManager.createBody(mInstanceId, component); } }); mDirty = true; mFlushes.add(domObject.ref); if (instance != null) { instance.commitUTStab(WXConst.DOM_MODULE, WXErrorCode.WX_SUCCESS); } }
九、WXRenderManager —-> DOM操作
public WXComponent createBodyOnDomThread(String instanceId, WXDomObject domObject) { WXRenderStatement statement = mRegistries.get(instanceId); if (statement == null) { return null; } return statement.createBodyOnDomThread(domObject); }
十、WXRenderStatement —> DOM对象转换组件
WXComponent createBodyOnDomThread(WXDomObject dom) { if (mWXSDKInstance == null) { return null; } WXDomObject domObject = new WXDomObject(); domObject.type = WXBasicComponentType.DIV; domObject.ref = "god"; mGodComponent = (WXVContainer) WXComponentFactory. newInstance(mWXSDKInstance, domObject, null, mInstanceId); mGodComponent.createView(null, -1); if (mGodComponent == null) { if (WXEnvironment.isApkDebugable()) { WXLogUtils.e("rootView failed!"); } //TODO error callback return null; } FrameLayout frameLayout = (FrameLayout) mGodComponent.getView(); ViewGroup.LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); frameLayout.setLayoutParams(layoutParams); frameLayout.setBackgroundColor(Color.TRANSPARENT); WXComponent component = generateComponentTree(dom, mGodComponent); mGodComponent.addChild(component); mRegistry.put(component.getRef(), component); return component; }// dom 对象转换 component treeprivate WXComponent generateComponentTree(WXDomObject dom, WXVContainer parent) { if (dom == null || parent == null) { return null; } WXComponent component = WXComponentFactory.newInstance(mWXSDKInstance, dom, parent, mInstanceId, parent.isLazy()); mRegistry.put(dom.ref, component); if (component instanceof WXVContainer) { WXVContainer parentC = (WXVContainer) component; int count = dom.childCount(); WXDomObject child = null; for (int i = 0; i < count; ++i) { child = dom.getChild(i); if (child != null) { parentC.addChild(generateComponentTree(child, parentC)); } } } return component; }
十一、WXRenderManager— > WXComponent 转换
// 得到Wx组件进行最终创建 public void createBody(String instanceId, WXComponent component) { WXRenderStatement statement = mRegistries.get(instanceId); if (statement == null) { return; } statement.createBody(component); }
十二、WXRenderStatement —> WX组件生成view
/** * 创建RootView; * @see com.taobao.weex.dom.WXDomStatement#createBody(JSONObject) */ void createBody(WXComponent component) { long start = System.currentTimeMillis(); component.createView(mGodComponent, -1); start = System.currentTimeMillis(); component.bind(null); if (component instanceof WXScroller) { WXScroller scroller = (WXScroller) component; if (scroller.getView() instanceof ScrollView) { mWXSDKInstance.setRootScrollView((ScrollView) scroller.getView()); } } // *** 创建成果rootview进行返回 *** mWXSDKInstance.setRootView(mGodComponent.getRealView()); if (mWXSDKInstance.getRenderStrategy() != WXRenderStrategy.APPEND_ONCE) { mWXSDKInstance.onViewCreated(mGodComponent); } }
十三、WXSDKInstance —> 接受view回调给activity
public void onViewCreated(final WXComponent component) { if (mRenderListener != null && mContext != null) { runOnUiThread(new Runnable() { @Override public void run() { if (mRenderListener != null && mContext != null) { mRootCom = component; mRenderListener.onViewCreated(WXSDKInstance.this, component.getView()); } } }); } }
十四、IndexActivity —> 接受view绘制UI
@Override public void onViewCreated(WXSDKInstance wxsdkInstance, View view) { Log.d("TAG", "onViewCreated"); if (flContainer != null) { flContainer.addView(view); } }
结束语
整个UI绘制流程就是这样的,猜测大家一定会掌握的,希望对大家有所帮助,谢谢您的观看!!!
4 0
- Weex Android SDK源码分析之界面渲染(下)
- Weex Android SDK源码分析之界面渲染(上)
- Weex Android SDK源码分析之Module(modal)
- Weex Android SDK源码分析之Module(navigator)
- Weex Android SDK源码分析之Module(stream)
- Weex Android SDK源码分析之Module(webview)
- Weex Android SDK源码分析之Module(animation)
- Weex Android SDK源码分析
- 代码干货 | Weex Android SDK源码分析
- 浅析weex之vdom渲染
- weex采坑之旅(三)Android SDK环境搭建
- 云客Drupal8源码分析之渲染数组(render array)
- weex sdk集成到Android工程三. weex服务项目搭建
- Android源码之“应用程序界面“分析一( 从settings开始)
- Android源码之“应用程序界面“分析二(PackageManager和PackageManagerService)
- Android 视图渲染过程的源码分析
- weex sdk集成到Android工程
- weex sdk集成到Android工程
- java 类反射机制
- 单向链表的创建、节点删除、链表输出、翻转(写法参考计蒜客数据结构课程)
- 提高项目10-编制三角函数表
- 高德地图——查询天气
- ASP.NET解决客户端服务器ID不一致-ClientID与ClientIDMode
- Weex Android SDK源码分析之界面渲染(下)
- 动态数据竞争验证方法(一)
- Electron的第一个应用
- ThreadPoolExecutor运转机制详解
- ubuntu更改swap的使用量
- 贝叶斯思想-dp进行简易中文分词
- 代理模式(Proxy)
- 51nod 1050 循环数组最大子段和
- 《构建之法----现代软件工程》书评