[WEEX-174][android] TemplateList Support Lifecycle and statefull component
Project: http://git-wip-us.apache.org/repos/asf/incubator-weex/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-weex/commit/886d859a Tree: http://git-wip-us.apache.org/repos/asf/incubator-weex/tree/886d859a Diff: http://git-wip-us.apache.org/repos/asf/incubator-weex/diff/886d859a Branch: refs/heads/master Commit: 886d859ab75ef892aad50506dace5818c06b66d2 Parents: 20c293f Author: jianbai.gbj <jianbai....@alibaba-inc.com> Authored: Wed Dec 20 15:07:01 2017 +0800 Committer: jianbai.gbj <jianbai....@alibaba-inc.com> Committed: Thu Feb 8 11:55:09 2018 +0800 ---------------------------------------------------------------------- .../java/com/alibaba/weex/WXApplication.java | 6 +- .../weex/extend/module/WXWsonTestModule.java | 58 ++ .../java/com/taobao/weex/WXEnvironment.java | 17 +- .../com/taobao/weex/bridge/WXBridgeManager.java | 112 +++- .../java/com/taobao/weex/common/Constants.java | 7 +- .../main/java/com/taobao/weex/dom/WXAttr.java | 19 +- .../java/com/taobao/weex/dom/WXDomModule.java | 7 +- .../java/com/taobao/weex/dom/WXDomObject.java | 29 +- .../main/java/com/taobao/weex/dom/WXEvent.java | 91 +-- .../main/java/com/taobao/weex/dom/WXStyle.java | 54 ++ .../dom/action/AbstractAddElementAction.java | 15 +- .../com/taobao/weex/dom/action/Actions.java | 6 + .../weex/dom/action/AddElementAction.java | 8 +- .../weex/dom/action/UpdateAttributeAction.java | 6 +- .../dom/action/UpdateComponentDataAction.java | 69 +++ .../com/taobao/weex/dom/binding/ELUtils.java | 1 + .../taobao/weex/dom/binding/WXStatement.java | 6 + .../java/com/taobao/weex/el/parse/Block.java | 3 +- .../java/com/taobao/weex/el/parse/Operator.java | 3 +- .../com/taobao/weex/el/parse/Operators.java | 11 +- .../java/com/taobao/weex/el/parse/Token.java | 3 +- .../weex/ui/component/ComponentUtils.java | 122 ++++ .../taobao/weex/ui/component/WXComponent.java | 110 +++- .../weex/ui/component/binding/Layouts.java | 23 +- .../weex/ui/component/binding/Statements.java | 224 +++++-- .../taobao/weex/ui/component/list/WXCell.java | 18 +- .../list/template/AsyncCellLoadTask.java | 128 ++++ .../list/template/CellDataManager.java | 272 +++++++++ .../list/template/CellRenderContext.java | 79 +++ .../list/template/CellRenderState.java | 122 ++++ .../component/list/template/DomTreeBuilder.java | 100 --- .../ui/component/list/template/PositionRef.java | 64 ++ .../template/VirtualComponentLifecycle.java | 45 ++ .../list/template/WXRecyclerTemplateList.java | 610 ++++++++++--------- .../java/com/taobao/weex/el/FailedCaseTest.java | 50 ++ .../ui/component/binding/StatementTest.java | 8 +- 36 files changed, 1940 insertions(+), 566 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/886d859a/android/playground/app/src/main/java/com/alibaba/weex/WXApplication.java ---------------------------------------------------------------------- diff --git a/android/playground/app/src/main/java/com/alibaba/weex/WXApplication.java b/android/playground/app/src/main/java/com/alibaba/weex/WXApplication.java index 41ca4cb..0561043 100644 --- a/android/playground/app/src/main/java/com/alibaba/weex/WXApplication.java +++ b/android/playground/app/src/main/java/com/alibaba/weex/WXApplication.java @@ -38,6 +38,7 @@ import com.alibaba.weex.extend.module.RenderModule; import com.alibaba.weex.extend.module.SyncTestModule; import com.alibaba.weex.extend.module.WXEventModule; import com.alibaba.weex.extend.module.WXTitleBar; +import com.alibaba.weex.extend.module.WXWsonTestModule; import com.facebook.drawee.backends.pipeline.Fresco; import com.taobao.weex.InitConfig; import com.taobao.weex.WXEnvironment; @@ -62,7 +63,8 @@ public class WXApplication extends Application { * Fresco.initialize(this,config); **/ // initDebugEnvironment(true, false, "DEBUG_SERVER_HOST"); - WXBridgeManager.updateGlobalConfig("wson_off"); + WXBridgeManager.updateGlobalConfig("wson_on"); + WXEnvironment.setOpenDebugLog(true); WXEnvironment.setApkDebugable(true); WXSDKEngine.addCustomOptions("appName", "WXSample"); WXSDKEngine.addCustomOptions("appGroup", "WXApp"); @@ -95,6 +97,8 @@ public class WXApplication extends Application { WXSDKEngine.registerModule("geolocation", GeolocationModule.class); WXSDKEngine.registerModule("titleBar", WXTitleBar.class); + + WXSDKEngine.registerModule("wsonTest", WXWsonTestModule.class); /** * override default image tag * WXSDKEngine.registerComponent("image", FrescoImageComponent.class); http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/886d859a/android/playground/app/src/main/java/com/alibaba/weex/extend/module/WXWsonTestModule.java ---------------------------------------------------------------------- diff --git a/android/playground/app/src/main/java/com/alibaba/weex/extend/module/WXWsonTestModule.java b/android/playground/app/src/main/java/com/alibaba/weex/extend/module/WXWsonTestModule.java new file mode 100644 index 0000000..b018678 --- /dev/null +++ b/android/playground/app/src/main/java/com/alibaba/weex/extend/module/WXWsonTestModule.java @@ -0,0 +1,58 @@ +package com.alibaba.weex.extend.module; + +import android.util.Log; + +import com.alibaba.fastjson.JSONObject; +import com.taobao.weex.annotation.JSMethod; +import com.taobao.weex.bridge.JSCallback; +import com.taobao.weex.common.WXModule; +import com.taobao.weex.wson.Wson; + +/** + * Created by furture on 2018/1/18. + */ + +public class WXWsonTestModule extends WXModule { + + @JSMethod(uiThread = false) + public boolean callPass(JSONObject params) { + if(params.get("refundId") != null){ + if(params.get("refundId").getClass() != Long.class){ + Log.e("Weex", "weex wson refundId failed case"); + return false; + } + return ((Long)params.get("refundId")) == 6419458776149741l; + } + + if(params.get("refundId2") != null){ + if(params.get("refundId2").getClass() != Long.class){ + Log.e("Weex", "weex wson refundId failed case"); + return false; + } + return ((Long)params.get("refundId2")) == 64194587761497416l; + } + + + + + return true; + } + + @JSMethod(uiThread = false) + public Object back(JSONObject params) { + JSONObject back = new JSONObject(params); + back.put("longMax", Long.MAX_VALUE); + back.put("longMin", Long.MIN_VALUE); + back.put("javaJSON", back.toJSONString()); + return back; + } + + @JSMethod(uiThread = false) + public void backAsync(JSONObject params, JSCallback callback) { + JSONObject back = new JSONObject(params); + back.put("longMax", Long.MAX_VALUE); + back.put("longMin", Long.MIN_VALUE); + back.put("javaJSON", back.toJSONString()); + callback.invoke(back); + } +} http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/886d859a/android/sdk/src/main/java/com/taobao/weex/WXEnvironment.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/WXEnvironment.java b/android/sdk/src/main/java/com/taobao/weex/WXEnvironment.java index e19570f..e6084d9 100644 --- a/android/sdk/src/main/java/com/taobao/weex/WXEnvironment.java +++ b/android/sdk/src/main/java/com/taobao/weex/WXEnvironment.java @@ -88,6 +88,8 @@ public class WXEnvironment { private static boolean isApkDebug = true; public static boolean isPerf = false; + private static boolean openDebugLog = false; + private static String sGlobalFontFamily; private static Map<String, String> options = new HashMap<>(); @@ -305,9 +307,20 @@ public class WXEnvironment { } } } - + + public static boolean isOpenDebugLog() { + return openDebugLog; + } + + public static void setOpenDebugLog(boolean openDebugLog) { + WXEnvironment.openDebugLog = openDebugLog; + } + public static void setApkDebugable(boolean debugable){ - isApkDebug = debugable; + isApkDebug = debugable; + if(!isApkDebug){ + openDebugLog = false; + } } } http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/886d859a/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java b/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java index 349b5f8..79e3127 100644 --- a/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java +++ b/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java @@ -78,6 +78,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Stack; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import static com.taobao.weex.bridge.WXModuleManager.getDomModule; import static com.taobao.weex.bridge.WXModuleManager.createDomModule; @@ -115,6 +117,7 @@ public class WXBridgeManager implements Callback, BactchExecutor { public static final String METHOD_REGISTER_COMPONENTS = "registerComponents"; public static final String METHOD_FIRE_EVENT = "fireEvent"; public static final String METHD_FIRE_EVENT_SYNC = "fireEventSync"; + public static final String METHD_COMPONENT_HOOK_SYNC = "componentHook"; public static final String METHOD_CALLBACK = "callback"; public static final String METHOD_REFRESH_INSTANCE = "refreshInstance"; public static final String METHOD_NOTIFY_TRIM_MEMORY = "notifyTrimMemory"; @@ -361,7 +364,7 @@ public class WXBridgeManager implements Callback, BactchExecutor { public Object callNativeModule(String instanceId, String module, String method, JSONArray arguments, Object options) { - if (WXEnvironment.isApkDebugable()) { + if (WXEnvironment.isOpenDebugLog()) { mLodBuilder.append("[WXBridgeManager] callNativeModule >>>> instanceId:").append(instanceId) .append(", module:").append(module).append(", method:").append(method).append(", arguments:").append(arguments); WXLogUtils.d(mLodBuilder.substring(0)); @@ -389,7 +392,7 @@ public class WXBridgeManager implements Callback, BactchExecutor { public Object callNativeModule(String instanceId, String module, String method, JSONArray arguments, JSONObject options) { - if (WXEnvironment.isApkDebugable()) { + if (WXEnvironment.isOpenDebugLog()) { mLodBuilder.append("[WXBridgeManager] callNativeModule >>>> instanceId:").append(instanceId) .append(", module:").append(module).append(", method:").append(method).append(", arguments:").append(arguments); WXLogUtils.d(mLodBuilder.substring(0)); @@ -420,7 +423,7 @@ public class WXBridgeManager implements Callback, BactchExecutor { } public Object callNativeComponent(String instanceId, String componentRef, String method, JSONArray arguments, Object options) { - if (WXEnvironment.isApkDebugable()) { + if (WXEnvironment.isOpenDebugLog()) { mLodBuilder.append("[WXBridgeManager] callNativeComponent >>>> instanceId:").append(instanceId) .append(", componentRef:").append(componentRef).append(", method:").append(method).append(", arguments:").append(arguments); WXLogUtils.d(mLodBuilder.substring(0)); @@ -458,7 +461,7 @@ public class WXBridgeManager implements Callback, BactchExecutor { return IWXBridge.INSTANCE_RENDERING_ERROR; } - if (WXEnvironment.isApkDebugable()) { + if (WXEnvironment.isOpenDebugLog()) { mLodBuilder.append("[WXBridgeManager] callNative >>>> instanceId:").append(instanceId) .append(", tasks:").append(tasks).append(", callback:").append(callback); WXLogUtils.d(mLodBuilder.substring(0)); @@ -534,12 +537,12 @@ public class WXBridgeManager implements Callback, BactchExecutor { return IWXBridge.INSTANCE_RENDERING_ERROR; } - // if (WXEnvironment.isApkDebugable()) { + if (WXEnvironment.isOpenDebugLog()) { mLodBuilder.append("[WXBridgeManager] callCreateBody >>>> instanceId:").append(instanceId) .append(", tasks:").append(tasks).append(", callback:").append(callback); WXLogUtils.d(mLodBuilder.substring(0)); mLodBuilder.setLength(0); - // } + } if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) { @@ -581,7 +584,7 @@ public class WXBridgeManager implements Callback, BactchExecutor { // callUpdateFinish public int callUpdateFinish(String instanceId, String callback) { - if (WXEnvironment.isApkDebugable()) { + if (WXEnvironment.isOpenDebugLog()) { mLodBuilder.append("[WXBridgeManager] callUpdateFinish >>>> instanceId:").append(instanceId) .append(", callback:").append(callback); WXLogUtils.d(mLodBuilder.substring(0)); @@ -615,12 +618,12 @@ public class WXBridgeManager implements Callback, BactchExecutor { // callCreateFinish public int callCreateFinish(String instanceId, String callback) { - // if (WXEnvironment.isApkDebugable()) { + if (WXEnvironment.isOpenDebugLog()) { mLodBuilder.append("[WXBridgeManager] callCreateFinish >>>> instanceId:").append(instanceId) .append(", callback:").append(callback); WXLogUtils.d(mLodBuilder.substring(0)); mLodBuilder.setLength(0); - // } + } if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) { return IWXBridge.DESTROY_INSTANCE; @@ -650,7 +653,7 @@ public class WXBridgeManager implements Callback, BactchExecutor { // callRefreshFinish public int callRefreshFinish(String instanceId, String callback) { - if (WXEnvironment.isApkDebugable()) { + if (WXEnvironment.isOpenDebugLog()) { mLodBuilder.append("[WXBridgeManager] callRefreshFinish >>>> instanceId:").append(instanceId) .append(", callback:").append(callback); WXLogUtils.d(mLodBuilder.substring(0)); @@ -693,7 +696,7 @@ public class WXBridgeManager implements Callback, BactchExecutor { return IWXBridge.INSTANCE_RENDERING_ERROR; } - if (WXEnvironment.isApkDebugable()) { + if (WXEnvironment.isOpenDebugLog()) { mLodBuilder.append("[WXBridgeManager] callUpdateAttrs >>>> instanceId:").append(instanceId) .append(", ref:").append(ref) .append(", task:").append(task) @@ -748,7 +751,7 @@ public class WXBridgeManager implements Callback, BactchExecutor { "task is empty", null); return IWXBridge.INSTANCE_RENDERING_ERROR; } - if (WXEnvironment.isApkDebugable()) { + if (WXEnvironment.isOpenDebugLog()) { mLodBuilder.append("[WXBridgeManager] callUpdateStyle >>>> instanceId:").append(instanceId) .append(", ref:").append(ref) .append(", task:").append(task) @@ -796,7 +799,7 @@ public class WXBridgeManager implements Callback, BactchExecutor { // callUpdateStyle public int callRemoveElement(String instanceId, String ref, String callback) { - if (WXEnvironment.isApkDebugable()) { + if (WXEnvironment.isOpenDebugLog()) { mLodBuilder.append("[WXBridgeManager] callRemoveElement >>>> instanceId:").append(instanceId) .append(", ref:").append(ref); WXLogUtils.d(mLodBuilder.substring(0)); @@ -835,7 +838,7 @@ public class WXBridgeManager implements Callback, BactchExecutor { // callMoveElement public int callMoveElement(String instanceId, String ref, String parentref, String index, String callback) { - if (WXEnvironment.isApkDebugable()) { + if (WXEnvironment.isOpenDebugLog()) { mLodBuilder.append("[WXBridgeManager] callMoveElement >>>> instanceId:").append(instanceId) .append(", parentref:").append(parentref) .append(", index:").append(index) @@ -872,13 +875,13 @@ public class WXBridgeManager implements Callback, BactchExecutor { public int callAddEvent(String instanceId, String ref, String event, String callback) { -// if (WXEnvironment.isApkDebugable()) { + if (WXEnvironment.isOpenDebugLog()) { mLodBuilder.append("[WXBridgeManager] callAddEvent >>>> instanceId:").append(instanceId) .append(", ref:").append(ref) .append(", event:").append(event); WXLogUtils.d(mLodBuilder.substring(0)); mLodBuilder.setLength(0); -// } + } if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) { return IWXBridge.DESTROY_INSTANCE; @@ -911,7 +914,7 @@ public class WXBridgeManager implements Callback, BactchExecutor { public int callRemoveEvent(String instanceId, String ref, String event, String callback) { - if (WXEnvironment.isApkDebugable()) { + if (WXEnvironment.isOpenDebugLog()) { mLodBuilder.append("[WXBridgeManager] callRemoveEvent >>>> instanceId:").append(instanceId) .append(", ref:").append(ref) .append(", event:").append(event); @@ -950,7 +953,7 @@ public class WXBridgeManager implements Callback, BactchExecutor { public int callAddElement(String instanceId, String ref, JSONObject dom, String index, String callback) { - if (WXEnvironment.isApkDebugable()) { + if (WXEnvironment.isOpenDebugLog()) { mLodBuilder.append("[WXBridgeManager] callNative::callAddElement >>>> instanceId:").append(instanceId) .append(", ref:").append(ref).append(", dom:").append(dom).append(", callback:").append(callback); WXLogUtils.d(mLodBuilder.substring(0)); @@ -1108,9 +1111,68 @@ public class WXBridgeManager implements Callback, BactchExecutor { } + /** - * aync call js event and return result in eventResult callback + * ref, type, data, domChanges * */ + public EventResult syncCallJSEventWithResult(final String method, final String instanceId, final List<Object> params, final Object... args) { + final CountDownLatch waitLatch = new CountDownLatch(1); + EventResult callback = new EventResult(){ + @Override + public void onCallback(Object result) { + super.onCallback(result); + waitLatch.countDown(); + } + }; + try{ + asyncCallJSEventWithResult(callback, method, instanceId, params, args); + waitLatch.await(100, TimeUnit.MILLISECONDS); + return callback; + }catch (Exception e){ + WXLogUtils.e("syncCallJSEventWithResult", e); + return callback; + } + } + + public void asyncCallJSEventVoidResult(final String method, final String instanceId, final List<Object> params, final Object... args) { + post(new Runnable() { + @Override + public void run() { + try{ + if (args == null || args.length == 0) { + return; + } + + ArrayList<Object> argsList = new ArrayList<>(); + for (Object arg : args) { + argsList.add(arg); + } + if (params != null) { + ArrayMap map = new ArrayMap(4); + map.put(KEY_PARAMS, params); + argsList.add(map); + } + + WXHashMap<String, Object> task = new WXHashMap<>(); + task.put(KEY_METHOD, method); + task.put(KEY_ARGS, argsList); + Object[] tasks = {task}; + WXJSObject[] jsArgs = { + new WXJSObject(WXJSObject.String, instanceId), + WXJsonUtils.wsonWXJSObject(tasks)}; + invokeExecJS(String.valueOf(instanceId), null, METHOD_CALL_JS, jsArgs, true); + jsArgs[0] = null; + jsArgs = null; + }catch (Exception e){ + WXLogUtils.e("asyncCallJSEventVoidResult" , e); + } + } + }); + } + + /** + * aync call js event and return result in eventResult callback + * */ private void asyncCallJSEventWithResult(final EventResult eventCallback, final String method, final String instanceId, final List<Object> params, final Object... args) { post(new Runnable() { @Override @@ -1153,7 +1215,7 @@ public class WXBridgeManager implements Callback, BactchExecutor { taskResult = null; jsArgs = null; }catch (Exception e){ - WXLogUtils.e("asyncCallJSEventWithResult "); + WXLogUtils.e("asyncCallJSEventWithResult" , e); } } }); @@ -1363,7 +1425,7 @@ public class WXBridgeManager implements Callback, BactchExecutor { return; } long start = System.currentTimeMillis(); - if (WXEnvironment.isApkDebugable()) { + if (WXEnvironment.isOpenDebugLog()) { WXLogUtils.d("refreshInstance >>>> instanceId:" + instanceId + ", data:" + refreshData.data + ", isDirty:" + refreshData.isDirty); } @@ -1524,7 +1586,7 @@ public class WXBridgeManager implements Callback, BactchExecutor { return; } try { - if (WXEnvironment.isApkDebugable()) { + if (WXEnvironment.isOpenDebugLog()) { WXLogUtils.d("createInstance >>>> instanceId:" + instance.getInstanceId() + ", options:" + WXJsonUtils.fromObjectToJSONString(options) @@ -1584,7 +1646,7 @@ public class WXBridgeManager implements Callback, BactchExecutor { private void invokeDestroyInstance(String instanceId) { try { - if (WXEnvironment.isApkDebugable()) { + if (WXEnvironment.isOpenDebugLog()) { WXLogUtils.d("destroyInstance >>>> instanceId:" + instanceId); } WXJSObject instanceIdObj = new WXJSObject(WXJSObject.String, @@ -1642,7 +1704,7 @@ public class WXBridgeManager implements Callback, BactchExecutor { public void invokeExecJS(String instanceId, String namespace, String function, WXJSObject[] args, boolean logTaskDetail) { - if (WXEnvironment.isApkDebugable()) { + if (WXEnvironment.isOpenDebugLog()) { mLodBuilder.append("callJS >>>> instanceId:").append(instanceId) .append("function:").append(function); if (logTaskDetail) { @@ -1656,7 +1718,7 @@ public class WXBridgeManager implements Callback, BactchExecutor { private byte[] invokeExecJSWithResult(String instanceId, String namespace, String function, WXJSObject[] args,boolean logTaskDetail){ - if (WXEnvironment.isApkDebugable()) { + if (WXEnvironment.isOpenDebugLog()) { mLodBuilder.append("callJS >>>> instanceId:").append(instanceId) .append("function:").append(function); if(logTaskDetail) { http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/886d859a/android/sdk/src/main/java/com/taobao/weex/common/Constants.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/common/Constants.java b/android/sdk/src/main/java/com/taobao/weex/common/Constants.java index 66c4df0..c107ee8 100644 --- a/android/sdk/src/main/java/com/taobao/weex/common/Constants.java +++ b/android/sdk/src/main/java/com/taobao/weex/common/Constants.java @@ -207,10 +207,9 @@ public class Constants { String LIST_DATA = "listData"; String LIST_DATA_ITEM ="alias"; String LIST_DATA_ITEM_INDEX = "index"; - String LIST_DATA_TEMPLATE_KEY = "templateKey"; - - String SLOT_TEMPLATE_TYPE = "templateType"; - String LIST_DATA_ITEM_ID = "itemId"; + String LIST_DATA_TEMPLATE_SWITCH_KEY = "switch"; + String SLOT_TEMPLATE_CASE = "case"; + String SLOT_TEMPLATE_DEFAULT = "default"; String CELL_INDEX = "cellIndex"; String TYPE_INDEX = "typeIndex"; } http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/886d859a/android/sdk/src/main/java/com/taobao/weex/dom/WXAttr.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/dom/WXAttr.java b/android/sdk/src/main/java/com/taobao/weex/dom/WXAttr.java index b05d46d..1025584 100644 --- a/android/sdk/src/main/java/com/taobao/weex/dom/WXAttr.java +++ b/android/sdk/src/main/java/com/taobao/weex/dom/WXAttr.java @@ -455,7 +455,7 @@ public class WXAttr implements Map<String, Object>,Cloneable { /** * filter dynamic state ment * */ - private Map<String, Object> filterBindingStatement(Map attrs) { + public Map<String, Object> filterBindingStatement(Map attrs) { if(attrs == null || attrs.size() == 0){ return attrs; } @@ -511,6 +511,13 @@ public class WXAttr implements Map<String, Object>,Cloneable { return true; } } + + if(WXStatement.WX_ONCE.equals(key)){ + if(mStatement == null){ + mStatement = new WXStatement(); + } + mStatement.put(key, true); + } return false; } @@ -519,11 +526,15 @@ public class WXAttr implements Map<String, Object>,Cloneable { } @Override - protected WXAttr clone(){ + protected WXAttr clone() { WXAttr wxAttr = new WXAttr(); wxAttr.skipFilterPutAll(attr); - wxAttr.mBindingAttrs = mBindingAttrs; - wxAttr.mStatement = mStatement; + if (mBindingAttrs != null) { + wxAttr.mBindingAttrs = new ArrayMap<>(mBindingAttrs); + } + if (mStatement != null){ + wxAttr.mStatement = new WXStatement(mStatement); + } return wxAttr; } } http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/886d859a/android/sdk/src/main/java/com/taobao/weex/dom/WXDomModule.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/dom/WXDomModule.java b/android/sdk/src/main/java/com/taobao/weex/dom/WXDomModule.java index 7ab97a9..b764630 100644 --- a/android/sdk/src/main/java/com/taobao/weex/dom/WXDomModule.java +++ b/android/sdk/src/main/java/com/taobao/weex/dom/WXDomModule.java @@ -61,6 +61,9 @@ public final class WXDomModule extends WXModule { public static final String UPDATE_FINISH = "updateFinish"; public static final String SCROLL_TO_ELEMENT = "scrollToElement"; public static final String ADD_RULE = "addRule"; + + public static final String UPDATE_COMPONENT_DATA = "updateComponentData"; + public static final String GET_COMPONENT_RECT = "getComponentRect"; public static final String WXDOM = "dom"; @@ -97,7 +100,9 @@ public final class WXDomModule extends WXModule { try { Action action = Actions.get(method,args); if(action == null){ - WXLogUtils.e("Unknown dom action."); + WXLogUtils.e("Unknown dom action " + + method + " " + args.toJSONString()); + return null; } if(action instanceof DOMAction){ postAction((DOMAction)action, CREATE_BODY.equals(method) || ADD_RULE.equals(method)); http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/886d859a/android/sdk/src/main/java/com/taobao/weex/dom/WXDomObject.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/dom/WXDomObject.java b/android/sdk/src/main/java/com/taobao/weex/dom/WXDomObject.java index d062a8a..dde66dc 100644 --- a/android/sdk/src/main/java/com/taobao/weex/dom/WXDomObject.java +++ b/android/sdk/src/main/java/com/taobao/weex/dom/WXDomObject.java @@ -134,6 +134,27 @@ public class WXDomObject extends CSSNode implements Cloneable,ImmutableDomObject mDomThreadNanos += (System.nanoTime() - startNanos); } + /** + * diff with tranverse tree, only tranverse update tree + * */ + public void traverseUpdateTree(Consumer...consumers){ + if (consumers == null) { + return; + } + if(!hasUpdate()){ + return; + } + for (Consumer consumer:consumers){ + consumer.accept(this); + } + int count = childCount(); + WXDomObject child; + for (int i = 0; i < count; ++i) { + child = getChild(i); + child.traverseTree(consumers); + } + } + public int getViewPortWidth() { return mViewPortWidth; @@ -230,15 +251,13 @@ public class WXDomObject extends CSSNode implements Cloneable,ImmutableDomObject this.mRef = (String) map.get("ref"); Object style = map.get("style"); if (style != null && style instanceof JSONObject) { - WXStyle styles = new WXStyle(); - styles.putAll((JSONObject) style,false); + WXStyle styles = new WXStyle((JSONObject) style,false); this.mStyles = styles; this.transition = WXTransition.fromMap(styles, this); } Object attr = map.get("attr"); if (attr != null && attr instanceof JSONObject) { WXAttr attrs = new WXAttr((JSONObject) attr); - //WXJsonUtils.putAll(attrs, (JSONObject) attr); this.mAttributes = attrs; } Object event = map.get("event"); @@ -470,7 +489,7 @@ public class WXDomObject extends CSSNode implements Cloneable,ImmutableDomObject if (mAttributes == null) { mAttributes = new WXAttr(); } - mAttributes.putAll(updates); + mAttributes.skipFilterPutAll(updates); if(hasNewLayout()){ markUpdateSeen(); } @@ -658,7 +677,7 @@ public class WXDomObject extends CSSNode implements Cloneable,ImmutableDomObject if (sDestroy.get()) { return null; } - if(cloneThis){ + if(isCloneThis()){ return this; } WXDomObject dom = null; http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/886d859a/android/sdk/src/main/java/com/taobao/weex/dom/WXEvent.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/dom/WXEvent.java b/android/sdk/src/main/java/com/taobao/weex/dom/WXEvent.java index fe7f8cf..3e99cfa 100644 --- a/android/sdk/src/main/java/com/taobao/weex/dom/WXEvent.java +++ b/android/sdk/src/main/java/com/taobao/weex/dom/WXEvent.java @@ -35,21 +35,29 @@ public class WXEvent extends ArrayList<String> implements Serializable, Cloneabl private static final long serialVersionUID = -8186587029452440107L; + + /** + * event data format + * { + * type: 'appear', + * params: [ + * { '@binding': 'index' }, + * 'static', + * { '@binding': 'item.name' }, + * { '@binding': '$event' } + * ] + * } + * */ + public static final String EVENT_KEY_TYPE = "type"; + public static final String EVENT_KEY_ARGS = "params"; + + /** * dynamic binding event args, can be null, only weex use * */ private ArrayMap mEventBindingArgs; private ArrayMap<String, List<Object>> mEventBindingArgsValues; - - @Override - public WXEvent clone() { - WXEvent event = (WXEvent) super.clone(); - event.mEventBindingArgs = mEventBindingArgs; - event.mEventBindingArgsValues = mEventBindingArgsValues; - return event; - } - @Override public void clear() { if(mEventBindingArgs != null){ @@ -63,13 +71,13 @@ public class WXEvent extends ArrayList<String> implements Serializable, Cloneabl public boolean remove(String o) { - if(mEventBindingArgs != null){ - mEventBindingArgs.remove(o); - } - if(mEventBindingArgsValues != null){ - mEventBindingArgsValues.remove(o); - } - return super.remove(o); + if(mEventBindingArgs != null){ + mEventBindingArgs.remove(o); + } + if(mEventBindingArgsValues != null){ + mEventBindingArgsValues.remove(o); + } + return super.remove(o); } /** @@ -89,14 +97,14 @@ public class WXEvent extends ArrayList<String> implements Serializable, Cloneabl if(event instanceof CharSequence){ String eventName = event.toString(); if(!contains(eventName)){ - add(eventName); + add(eventName); } }else if(event instanceof JSONObject){ JSONObject bindings = (JSONObject) event; String eventName = bindings.getString(WXEvent.EVENT_KEY_TYPE); Object args = bindings.get(WXEvent.EVENT_KEY_ARGS); if (eventName != null) { - putEventBindingArgs(eventName, args); + putEventBindingArgs(eventName, args); } } } @@ -116,41 +124,40 @@ public class WXEvent extends ArrayList<String> implements Serializable, Cloneabl } public void putEventBindingArgs(String event, Object args){ - if(!contains(event)){ - add(event); - } - if(args != null){ - if(mEventBindingArgs == null){ - mEventBindingArgs = new ArrayMap(); - } - mEventBindingArgs.put(event, ELUtils.bindingBlock(args)); + if(!contains(event)){ + add(event); + } + if(args != null){ + if(mEventBindingArgs == null){ + mEventBindingArgs = new ArrayMap(); } + mEventBindingArgs.put(event, ELUtils.bindingBlock(args)); + } } public void putEventBindingArgsValue(String event, List<Object> value){ if(mEventBindingArgsValues == null){ - mEventBindingArgsValues = new ArrayMap(); + mEventBindingArgsValues = new ArrayMap(); } if(value == null){ mEventBindingArgsValues.remove(event); }else{ - mEventBindingArgsValues.put(event, value); + mEventBindingArgsValues.put(event, value); } } - /** - * event data format - * { - * type: 'appear', - * params: [ - * { '@binding': 'index' }, - * 'static', - * { '@binding': 'item.name' }, - * { '@binding': '$event' } - * ] - * } - * */ - public static final String EVENT_KEY_TYPE = "type"; - public static final String EVENT_KEY_ARGS = "params"; + + @Override + public WXEvent clone() { + WXEvent event = new WXEvent(); + event.addAll(this); + if(mEventBindingArgs != null) { + event.mEventBindingArgs = new ArrayMap(mEventBindingArgs); + } + event.mEventBindingArgsValues = null; //this should not be clone, it dynamic args + return event; + } + + } http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/886d859a/android/sdk/src/main/java/com/taobao/weex/dom/WXStyle.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/dom/WXStyle.java b/android/sdk/src/main/java/com/taobao/weex/dom/WXStyle.java index 6dc444a..ff1842a 100644 --- a/android/sdk/src/main/java/com/taobao/weex/dom/WXStyle.java +++ b/android/sdk/src/main/java/com/taobao/weex/dom/WXStyle.java @@ -26,11 +26,14 @@ import android.text.Layout; import android.text.TextUtils; import com.taobao.weex.common.Constants; +import com.taobao.weex.dom.binding.ELUtils; +import com.taobao.weex.dom.binding.WXStatement; import com.taobao.weex.dom.flex.CSSAlign; import com.taobao.weex.dom.flex.CSSFlexDirection; import com.taobao.weex.dom.flex.CSSJustify; import com.taobao.weex.dom.flex.CSSPositionType; import com.taobao.weex.dom.flex.CSSWrap; +import com.taobao.weex.el.parse.Parser; import com.taobao.weex.ui.component.WXText; import com.taobao.weex.ui.component.WXTextDecoration; import com.taobao.weex.utils.WXUtils; @@ -41,6 +44,9 @@ import java.util.Iterator; import java.util.Map; import java.util.Set; +import static com.taobao.weex.dom.binding.ELUtils.COMPONENT_PROPS; +import static com.taobao.weex.dom.binding.ELUtils.EXCLUDES_BINDING; + /** * Store value of component style * @@ -54,11 +60,20 @@ public class WXStyle implements Map<String, Object>,Cloneable { private Map<String,Map<String,Object>> mPesudoStyleMap = new ArrayMap<>();// clz_group:{styleMap} private Map<String,Object> mPesudoResetStyleMap = new ArrayMap<>(); + /** + * dynamic binding attrs, can be null, only weex use + * */ + private ArrayMap<String, Object> mBindingStyle; public WXStyle(){ mStyles = new ArrayMap<>(); } + public WXStyle(Map<String, Object> mStyles, boolean byPesudo) { + this(); + this.putAll(filterBindingStyles(mStyles), byPesudo); + } + @Nullable public String getBlur() { if(get(Constants.Name.FILTER) == null) { @@ -749,6 +764,7 @@ public class WXStyle implements Map<String, Object>,Cloneable { protected WXStyle clone(){ WXStyle style = new WXStyle(); style.mStyles.putAll(this.mStyles); + style.mBindingStyle = mBindingStyle; for(Entry<String,Map<String,Object>> entry:this.mPesudoStyleMap.entrySet()){ Map<String,Object> valueClone = new ArrayMap<>(); @@ -759,4 +775,42 @@ public class WXStyle implements Map<String, Object>,Cloneable { style.mPesudoResetStyleMap.putAll(this.mPesudoResetStyleMap); return style; } + + + /** + * filter dynamic state ment + * */ + private Map<String, Object> filterBindingStyles(Map styles) { + if(styles == null || styles.size() == 0){ + return styles; + } + Set<Map.Entry<String,Object>> entries = styles.entrySet(); + Iterator<Entry<String,Object>> it = entries.iterator(); + while (it.hasNext()){ + Map.Entry<String,Object> entry = it.next(); + if(filterBindingStyle(entry.getKey(), entry.getValue())){ + it.remove(); + } + } + return styles; + } + + /** + * filter dynamic attrs and statements + * */ + private boolean filterBindingStyle(String key, Object value) { + if(ELUtils.isBinding(value)){ + if(mBindingStyle == null){ + mBindingStyle = new ArrayMap<String, Object>(); + } + value = ELUtils.bindingBlock(value); + mBindingStyle.put(key, value); + return true; + } + return false; + } + + public ArrayMap<String, Object> getBindingStyle() { + return mBindingStyle; + } } http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/886d859a/android/sdk/src/main/java/com/taobao/weex/dom/action/AbstractAddElementAction.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/dom/action/AbstractAddElementAction.java b/android/sdk/src/main/java/com/taobao/weex/dom/action/AbstractAddElementAction.java index cbe5a53..b6a27fb 100644 --- a/android/sdk/src/main/java/com/taobao/weex/dom/action/AbstractAddElementAction.java +++ b/android/sdk/src/main/java/com/taobao/weex/dom/action/AbstractAddElementAction.java @@ -27,9 +27,11 @@ import com.taobao.weex.common.WXErrorCode; import com.taobao.weex.dom.DOMAction; import com.taobao.weex.dom.DOMActionContext; import com.taobao.weex.dom.RenderAction; +import com.taobao.weex.dom.WXCellDomObject; import com.taobao.weex.dom.WXDomObject; import com.taobao.weex.tracing.Stopwatch; import com.taobao.weex.tracing.WXTracing; +import com.taobao.weex.ui.component.WXBasicComponentType; import com.taobao.weex.ui.component.WXComponent; import com.taobao.weex.ui.component.WXComponentFactory; import com.taobao.weex.ui.component.WXVContainer; @@ -132,8 +134,19 @@ public abstract class AbstractAddElementAction extends TraceableAction implement } Stopwatch.split("createComponent"); - context.addDomInfo(domObject.getRef(), component); + boolean needAddDomInfo = true; + if(domObject.getType().equals(WXBasicComponentType.CELL_SLOT) + && domObject instanceof WXCellDomObject){ + needAddDomInfo = false; + } + + if(needAddDomInfo) { + context.addDomInfo(domObject.getRef(), component); + } + + context.postRenderTask(this); + addAnimationForDomTree(context, domObject); // instance.commitUTStab(IWXUserTrackAdapter.DOM_MODULE, WXErrorCode.WX_SUCCESS); http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/886d859a/android/sdk/src/main/java/com/taobao/weex/dom/action/Actions.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/dom/action/Actions.java b/android/sdk/src/main/java/com/taobao/weex/dom/action/Actions.java index c284997..9f60765 100644 --- a/android/sdk/src/main/java/com/taobao/weex/dom/action/Actions.java +++ b/android/sdk/src/main/java/com/taobao/weex/dom/action/Actions.java @@ -42,6 +42,7 @@ import static com.taobao.weex.dom.WXDomModule.REMOVE_ELEMENT; import static com.taobao.weex.dom.WXDomModule.REMOVE_EVENT; import static com.taobao.weex.dom.WXDomModule.SCROLL_TO_ELEMENT; import static com.taobao.weex.dom.WXDomModule.UPDATE_ATTRS; +import static com.taobao.weex.dom.WXDomModule.UPDATE_COMPONENT_DATA; import static com.taobao.weex.dom.WXDomModule.UPDATE_FINISH; import static com.taobao.weex.dom.WXDomModule.UPDATE_STYLE; @@ -121,6 +122,11 @@ public class Actions { return null; } return new InvokeMethodAction(args.getString(0),args.getString(1),args.getJSONArray(2)); + case UPDATE_COMPONENT_DATA: + if(args == null || args.size() < 3){ + return null; + } + return new UpdateComponentDataAction(args.getString(0), args.getJSONObject(1), args.getString(2)); } return null; http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/886d859a/android/sdk/src/main/java/com/taobao/weex/dom/action/AddElementAction.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/dom/action/AddElementAction.java b/android/sdk/src/main/java/com/taobao/weex/dom/action/AddElementAction.java index 2958ea5..87f5d56 100644 --- a/android/sdk/src/main/java/com/taobao/weex/dom/action/AddElementAction.java +++ b/android/sdk/src/main/java/com/taobao/weex/dom/action/AddElementAction.java @@ -20,13 +20,15 @@ package com.taobao.weex.dom.action; import com.alibaba.fastjson.JSONObject; import com.taobao.weex.WXSDKInstance; -import com.taobao.weex.adapter.IWXUserTrackAdapter; import com.taobao.weex.common.WXErrorCode; import com.taobao.weex.dom.DOMActionContext; import com.taobao.weex.dom.RenderActionContext; +import com.taobao.weex.dom.WXCellDomObject; import com.taobao.weex.dom.WXDomObject; import com.taobao.weex.tracing.Stopwatch; import com.taobao.weex.tracing.WXTracing; +import com.taobao.weex.ui.component.ComponentUtils; +import com.taobao.weex.ui.component.WXBasicComponentType; import com.taobao.weex.ui.component.WXComponent; import com.taobao.weex.ui.component.WXVContainer; import com.taobao.weex.utils.WXLogUtils; @@ -60,6 +62,10 @@ final class AddElementAction extends AbstractAddElementAction { .append("!(comp instanceof WXVContainer)"); return null; } + if(domObject.getType().equals(WXBasicComponentType.CELL_SLOT) + && domObject instanceof WXCellDomObject){ + return ComponentUtils.buildTree(domObject, (WXVContainer) comp); + } return generateComponentTree(context, domObject, (WXVContainer) comp); } http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/886d859a/android/sdk/src/main/java/com/taobao/weex/dom/action/UpdateAttributeAction.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/dom/action/UpdateAttributeAction.java b/android/sdk/src/main/java/com/taobao/weex/dom/action/UpdateAttributeAction.java index bbeeea1..0591f73 100644 --- a/android/sdk/src/main/java/com/taobao/weex/dom/action/UpdateAttributeAction.java +++ b/android/sdk/src/main/java/com/taobao/weex/dom/action/UpdateAttributeAction.java @@ -60,9 +60,11 @@ class UpdateAttributeAction extends TraceableAction implements DOMAction, Render } return; } - + domObject.getAttrs().filterBindingStatement(mData); domObject.updateAttr(mData); - context.postRenderTask(this); + if(mData.size() > 0) { + context.postRenderTask(this); + } } @Override http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/886d859a/android/sdk/src/main/java/com/taobao/weex/dom/action/UpdateComponentDataAction.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/dom/action/UpdateComponentDataAction.java b/android/sdk/src/main/java/com/taobao/weex/dom/action/UpdateComponentDataAction.java new file mode 100644 index 0000000..347c886 --- /dev/null +++ b/android/sdk/src/main/java/com/taobao/weex/dom/action/UpdateComponentDataAction.java @@ -0,0 +1,69 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.taobao.weex.dom.action; + +import android.text.TextUtils; + +import com.alibaba.fastjson.JSONObject; +import com.taobao.weex.bridge.SimpleJSCallback; +import com.taobao.weex.dom.RenderAction; +import com.taobao.weex.dom.RenderActionContext; +import com.taobao.weex.ui.component.WXComponent; +import com.taobao.weex.ui.component.list.template.CellDataManager; +import com.taobao.weex.ui.component.list.template.WXRecyclerTemplateList; +import com.taobao.weex.utils.WXLogUtils; + + +/** + * Created by furture on 2018/1/23. + */ + +public class UpdateComponentDataAction implements RenderAction { + + private String virtualComponentId; + private JSONObject data; + private String callback; + + public UpdateComponentDataAction(String virtualComponentId, + JSONObject data, String callback) { + this.virtualComponentId = virtualComponentId; + this.data = data; + this.callback = callback; + } + + @Override + public void executeRender(RenderActionContext context) { + String ref = CellDataManager.getListRef(virtualComponentId); + if(TextUtils.isEmpty(ref)){ + WXLogUtils.e("wrong virtualComponentId split error " + virtualComponentId); + return; + } + WXComponent component = context.getComponent(ref); + if(component instanceof WXRecyclerTemplateList){ + WXRecyclerTemplateList templateList = (WXRecyclerTemplateList) component; + templateList.getCellDataManager().updateVirtualComponentData(virtualComponentId, data); + templateList.notifyUpdateList(); + SimpleJSCallback jsCallback = new SimpleJSCallback(component.getInstanceId(), callback); + jsCallback.invoke(true); + }else{ + WXLogUtils.e("recycler-list wrong virtualComponentId " + virtualComponentId); + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/886d859a/android/sdk/src/main/java/com/taobao/weex/dom/binding/ELUtils.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/dom/binding/ELUtils.java b/android/sdk/src/main/java/com/taobao/weex/dom/binding/ELUtils.java index 8202a46..dac03b2 100644 --- a/android/sdk/src/main/java/com/taobao/weex/dom/binding/ELUtils.java +++ b/android/sdk/src/main/java/com/taobao/weex/dom/binding/ELUtils.java @@ -39,6 +39,7 @@ public class ELUtils { * */ public static final String IS_COMPONENT_ROOT = "@isComponentRoot"; + public static final String COMPONENT_PROPS = "@componentProps"; public static final String[] EXCLUDES_BINDING = {"clickEventParams"}; http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/886d859a/android/sdk/src/main/java/com/taobao/weex/dom/binding/WXStatement.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/dom/binding/WXStatement.java b/android/sdk/src/main/java/com/taobao/weex/dom/binding/WXStatement.java index ca20dca..6a760cb 100644 --- a/android/sdk/src/main/java/com/taobao/weex/dom/binding/WXStatement.java +++ b/android/sdk/src/main/java/com/taobao/weex/dom/binding/WXStatement.java @@ -63,6 +63,12 @@ public class WXStatement extends ArrayMap<String, Object> implements Cloneable * */ public static final String WX_IF = "[[match]]"; + + /** + * once statement + * */ + public static final String WX_ONCE = "[[once]]"; + public WXStatement() { } http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/886d859a/android/sdk/src/main/java/com/taobao/weex/el/parse/Block.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/el/parse/Block.java b/android/sdk/src/main/java/com/taobao/weex/el/parse/Block.java index 5d15220..6c3e29a 100644 --- a/android/sdk/src/main/java/com/taobao/weex/el/parse/Block.java +++ b/android/sdk/src/main/java/com/taobao/weex/el/parse/Block.java @@ -57,7 +57,6 @@ class Block extends Token { return token.execute(context); } - /** @Override public String toString() { if(getType() == TYPE_ARRAY){ @@ -68,5 +67,5 @@ class Block extends Token { } return "{" + tokens + '}'; } - }*/ + } } http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/886d859a/android/sdk/src/main/java/com/taobao/weex/el/parse/Operator.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/el/parse/Operator.java b/android/sdk/src/main/java/com/taobao/weex/el/parse/Operator.java index d592579..d597be8 100644 --- a/android/sdk/src/main/java/com/taobao/weex/el/parse/Operator.java +++ b/android/sdk/src/main/java/com/taobao/weex/el/parse/Operator.java @@ -93,7 +93,6 @@ class Operator extends Token { } } - /** @Override public String toString() { if(Operators.AND_NOT.equals(getToken())){ @@ -103,5 +102,5 @@ class Operator extends Token { return "{" + first + getToken() + second + "}"; } return "{" + self + getToken() + first + ":" + second + "}"; - }*/ + } } http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/886d859a/android/sdk/src/main/java/com/taobao/weex/el/parse/Operators.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/el/parse/Operators.java b/android/sdk/src/main/java/com/taobao/weex/el/parse/Operators.java index b2e1c02..a8de759 100644 --- a/android/sdk/src/main/java/com/taobao/weex/el/parse/Operators.java +++ b/android/sdk/src/main/java/com/taobao/weex/el/parse/Operators.java @@ -18,6 +18,9 @@ */ package com.taobao.weex.el.parse; +import com.taobao.weex.WXEnvironment; +import com.taobao.weex.ui.component.list.template.CellRenderContext; + import java.lang.reflect.Array; import java.util.ArrayList; import java.util.HashMap; @@ -63,6 +66,12 @@ public class Operators { if(context == null){ return null; } + if(context instanceof CellRenderContext){ + if(WXEnvironment.isApkDebugable()){ + throw new IllegalArgumentException("rong context CellRenderContext, you should pass it's stack"); + } + context = ((CellRenderContext) context).stack; + } if(context instanceof ArrayStack){ ArrayStack stack = (ArrayStack) context; for(int index=stack.size()-1; index >= 0; index--){ @@ -257,7 +266,7 @@ public class Operators { } Object leftValue = null; if(left != null){ - leftValue = left.execute(context);; + leftValue = left.execute(context); } Object rightValue = null; if(right != null) { http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/886d859a/android/sdk/src/main/java/com/taobao/weex/el/parse/Token.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/el/parse/Token.java b/android/sdk/src/main/java/com/taobao/weex/el/parse/Token.java index 88a6ff8..44f9135 100644 --- a/android/sdk/src/main/java/com/taobao/weex/el/parse/Token.java +++ b/android/sdk/src/main/java/com/taobao/weex/el/parse/Token.java @@ -74,11 +74,10 @@ public class Token { throw new IllegalArgumentException("unhandled token type " + type); } - /*** @Override public String toString() { return "{" + token + "," + type + '}'; - }*/ + } public String getToken() { return token; http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/886d859a/android/sdk/src/main/java/com/taobao/weex/ui/component/ComponentUtils.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/ComponentUtils.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/ComponentUtils.java new file mode 100644 index 0000000..b28a94f --- /dev/null +++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/ComponentUtils.java @@ -0,0 +1,122 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.taobao.weex.ui.component; + +import com.taobao.weex.WXEnvironment; +import com.taobao.weex.WXSDKManager; +import com.taobao.weex.dom.DOMActionContext; +import com.taobao.weex.dom.WXDomObject; +import com.taobao.weex.dom.action.TraceableAction; +import com.taobao.weex.utils.WXLogUtils; + +/** + * Created by furture on 2018/1/25. + */ + +public class ComponentUtils { + + private static final String TAG = "ComponentUtils"; + + /** + * init component if component is lazy, + * if component is not lazy, do nothing + * */ + public static void initLazyComponent(WXComponent component, WXVContainer mParent){ + if(component.isLazy()){ + component.lazy(false); + if(mParent != null){ + int index = mParent.indexOf(component); + mParent.createChildViewAt(index); + }else { + component.createView(); + } + component.applyLayoutAndEvent(component); + component.bindData(component); + } + } + + /** + * build component tree and dom tree for template list + * */ + public static synchronized final WXComponent buildTree(WXDomObject domObject, WXVContainer parent){ + DOMActionContext domActionContext = WXSDKManager.getInstance().getWXDomManager().getDomContext(parent.getInstanceId()); + if(domActionContext == null){ + return null; + } + DomTreeBuilder builder = new DomTreeBuilder(); + domObject.traverseTree( + domActionContext.getAddDOMConsumer(), + domActionContext.getApplyStyleConsumer() + ); + return builder.buildComponentTree(domActionContext, domObject, parent); + } + + + /** + * dom tree build + * */ + static class DomTreeBuilder extends TraceableAction { + + private WXComponent buildComponentTree(DOMActionContext context, WXDomObject dom, WXVContainer parent) { + if (dom == null) { + return null; + } + long startNanos = System.nanoTime(); + dom.setCloneThis(true); + WXComponent component = WXComponentFactory.newInstance(context.getInstance(), dom, parent); + if (component != null) { + component.mTraceInfo.domThreadStart = dom.mDomThreadTimestamp; + component.mTraceInfo.rootEventId = mTracingEventId; + component.mTraceInfo.domQueueTime = mDomQueueTime; + } + context.registerComponent(dom.getRef(), component); + if (component instanceof WXVContainer) { + WXVContainer container = (WXVContainer) component; + WXDomObject parentDom = (WXDomObject) container.getDomObject(); + for (int i = 0; i < dom.childCount(); ++i) { + WXDomObject child = dom.getChild(i); + if (child != null) { + WXComponent childComponent = buildComponentTree(context, child, container); + container.addChild(childComponent); + WXDomObject childDomObject = (WXDomObject) childComponent.getDomObject(); + if(childDomObject != child) { + int index = parentDom.index(child); + parentDom.add(childDomObject, index); + if(index >= 0) { + parentDom.remove(child); + i--; + } + RuntimeException exception = new IllegalArgumentException(childDomObject.getClass().getName() + + " not support clone this"); + WXLogUtils.e("weex", exception); + if(WXEnvironment.isApkDebugable()){ + throw exception; + } + } + } + } + } + dom.setCloneThis(false); + if (component != null) { + component.mTraceInfo.domThreadNanos = System.nanoTime() - startNanos; + } + return component; + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/886d859a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXComponent.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXComponent.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXComponent.java index 0aff8a5..2e234ba 100644 --- a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXComponent.java +++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXComponent.java @@ -79,6 +79,7 @@ import com.taobao.weex.tracing.Stopwatch; import com.taobao.weex.tracing.WXTracing; import com.taobao.weex.ui.IFComponentHolder; import com.taobao.weex.ui.animation.WXAnimationModule; +import com.taobao.weex.ui.component.binding.Statements; import com.taobao.weex.ui.component.pesudo.OnActivePseudoListener; import com.taobao.weex.ui.component.pesudo.PesudoStatus; import com.taobao.weex.ui.component.pesudo.TouchActivePseudoListener; @@ -124,7 +125,7 @@ public abstract class WXComponent<T extends View> implements IWXObject, IWXActi public static final String PROP_FS_WRAP_CONTENT = "w"; private int mFixedProp = 0; - public static int mComponentNum = 0; + public static volatile int mComponentNum = 0; /** package **/ T mHost; private volatile WXVContainer mParent; @@ -158,6 +159,7 @@ public abstract class WXComponent<T extends View> implements IWXObject, IWXActi private boolean mNeedLayoutOnAnimation = false; private String mLastBoxShadowId; + public WXTracing.TraceInfo mTraceInfo = new WXTracing.TraceInfo(); public static final int TYPE_COMMON = 0; @@ -165,6 +167,7 @@ public abstract class WXComponent<T extends View> implements IWXObject, IWXActi private boolean waste = false; + //Holding the animation bean when component is uninitialized public void postAnimation(WXAnimationModule.AnimationHolder holder) { this.mAnimationHolder = holder; @@ -348,6 +351,12 @@ public abstract class WXComponent<T extends View> implements IWXObject, IWXActi if(mDomObj.getEvents() != null && mDomObj.getEvents().getEventBindingArgsValues() != null){ eventArgsValues = mDomObj.getEvents().getEventBindingArgsValues().get(type); } + if(params != null){ + String componentId = Statements.getComponentId(this); + if(componentId != null) { + params.put("componentId", componentId); + } + } mInstance.fireEvent(mCurrentRef, type, params,domChanges, eventArgsValues, callback); } } @@ -371,6 +380,9 @@ public abstract class WXComponent<T extends View> implements IWXObject, IWXActi * @return true for lazy */ public boolean isLazy() { + if(mLazy){ + return true; + } return mParent != null && mParent.isLazy(); } @@ -1974,51 +1986,85 @@ public abstract class WXComponent<T extends View> implements IWXObject, IWXActi } } + protected boolean isRippleEnabled() { + try { + Object obj = getDomObject().getAttrs().get(Constants.Name.RIPPLE_ENABLED); + return WXUtils.getBoolean(obj, false); + } catch (Throwable t) { + //ignore + } + return false; + } + + + public boolean isWaste() { return waste; } + /** + * mark node waste, + * if node is waster should hidden, and dom tree should allow not show + * */ public void setWaste(boolean waste) { if(this.waste != waste){ this.waste = waste; WXDomObject domObject = (WXDomObject) getDomObject(); if(waste){ - getDomObject().getStyles().put(Constants.Name.VISIBILITY, Constants.Value.HIDDEN); - if(domObject.getAttrs().getStatement() == null) { - domObject.setVisible(false); - if (getHostView() != null) { - getHostView().setVisibility(View.GONE); - } - return; - } - if(Constants.Value.VISIBLE.equals(domObject.getAttrs().get(Constants.Name.VIF_FALSE))){ - domObject.setVisible(true); - if(getHostView() != null){ - getHostView().setVisibility(View.VISIBLE); - } - }else{ - domObject.setVisible(false); - if(getHostView() != null){ - getHostView().setVisibility(View.GONE); - } - } + //update dom not show, and put style to hidden + domObject.setVisible(false); + domObject.getStyles().put(Constants.Name.VISIBILITY, Constants.Value.HIDDEN); + //if component not init, mark lazy init when use, reduce view count + if(getHostView() == null){ + if(!mLazy){ + lazy(true); + } + }else{ + getHostView().setVisibility(View.GONE); + } }else{ - domObject.setVisible(true); - if(getHostView() != null){ + domObject.setVisible(true); + domObject.getStyles().put(Constants.Name.VISIBILITY, Constants.Value.VISIBLE); + if(getHostView() == null){ + if(mLazy) { // when parent is lazy just mark node lazy false + if(mParent != null && mParent.isLazy()){ + lazy(false); + }else{ + ComponentUtils.initLazyComponent(this, mParent); + } + } + }else{ getHostView().setVisibility(View.VISIBLE); - } - getDomObject().getStyles().put(Constants.Name.VISIBILITY, Constants.Value.VISIBLE); + } } } } - protected boolean isRippleEnabled() { - try { - Object obj = getDomObject().getAttrs().get(Constants.Name.RIPPLE_ENABLED); - return WXUtils.getBoolean(obj, false); - } catch (Throwable t) { - //ignore - } - return false; + + /** component key id in native, + * differ with ref, ref + position + * */ + public String getViewTreeKey(){ + if(mViewTreeKey == null){ + if(getParent() == null){ + mViewTreeKey = getRef(); + }else{ + mViewTreeKey = getRef() + "_" + getParent().indexOf(this); + } + } + return mViewTreeKey; + } + + private String mViewTreeKey; + + + /** + * node is lazy + * */ + private boolean mLazy = false; + + /***/ + public void lazy(boolean lazy) { + mLazy = lazy; } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/886d859a/android/sdk/src/main/java/com/taobao/weex/ui/component/binding/Layouts.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/binding/Layouts.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/binding/Layouts.java index 9dea0ff..3357882 100644 --- a/android/sdk/src/main/java/com/taobao/weex/ui/component/binding/Layouts.java +++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/binding/Layouts.java @@ -21,14 +21,12 @@ package com.taobao.weex.ui.component.binding; import android.os.AsyncTask; -import android.util.Log; import com.taobao.weex.WXEnvironment; import com.taobao.weex.WXSDKInstance; import com.taobao.weex.common.Constants; import com.taobao.weex.dom.WXDomObject; import com.taobao.weex.dom.flex.CSSLayoutContext; -import com.taobao.weex.dom.flex.CSSNode; import com.taobao.weex.ui.component.WXComponent; import com.taobao.weex.ui.component.WXVContainer; import com.taobao.weex.ui.component.list.template.TemplateViewHolder; @@ -87,10 +85,14 @@ public class Layouts { try{ long start = System.currentTimeMillis(); doLayout(component, layoutContext); - if(WXEnvironment.isApkDebugable()){ + if(WXEnvironment.isOpenDebugLog() && WXRecyclerTemplateList.ENABLE_TRACE_LOG) { WXLogUtils.d(WXRecyclerTemplateList.TAG, "WXTemplateList doSafeLayout" + - component.getDomObject().getAttrs().get(Constants.Name.Recycler.SLOT_TEMPLATE_TYPE) + Thread.currentThread().getName() + " doSafeLayout used " + - (System.currentTimeMillis() - start)); + component.getDomObject().getAttrs().get(Constants.Name.Recycler.SLOT_TEMPLATE_CASE) + Thread.currentThread().getName() + " doSafeLayout used " + + (System.currentTimeMillis() - start)); + } + if(!(component.getLayoutHeight() > 0)){ + WXLogUtils.e(WXRecyclerTemplateList.TAG, " WXTemplateList doSafeLayout wrong template " + + component.getDomObject().getAttrs().get(Constants.Name.Recycler.SLOT_TEMPLATE_CASE) + " cell height " + component.getLayoutHeight()); } }catch (Exception e){ if(WXEnvironment.isApkDebugable()){ @@ -102,7 +104,7 @@ public class Layouts { private static void doLayout(WXComponent component, final CSSLayoutContext layoutContext){ WXDomObject domObject = (WXDomObject) component.getDomObject(); final WXSDKInstance instance = component.getInstance(); - domObject.traverseTree(new WXDomObject.Consumer() { + domObject.traverseUpdateTree(new WXDomObject.Consumer() { @Override public void accept(WXDomObject dom) { if(instance == null || instance.isDestroy()){ @@ -111,18 +113,24 @@ public class Layouts { if(!dom.hasUpdate()){ return; } + if(!dom.isShow()){ //not show just skip + return; + } dom.layoutBefore(); } }); if(instance != null && !instance.isDestroy()){ domObject.calculateLayout(layoutContext); } - domObject.traverseTree( new WXDomObject.Consumer() { + domObject.traverseUpdateTree( new WXDomObject.Consumer() { @Override public void accept(WXDomObject dom) { if(instance == null || instance.isDestroy()){ return; } + if(!dom.isShow()){ + return; + } if (dom.hasUpdate()) { dom.layoutAfter(); } @@ -140,7 +148,6 @@ public class Layouts { * */ public static final void setLayout(WXComponent component, boolean force){ if(component.isWaste()){ - setLayoutWaste(component, force); return; } WXDomObject domObject = (WXDomObject) component.getDomObject();