You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@weex.apache.org by ky...@apache.org on 2018/04/28 06:54:00 UTC

[32/48] incubator-weex git commit: * [android] Merge WeexCore-master to master.

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/android/sdk/src/main/java/com/taobao/weex/dom/transition/WXTransition.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/dom/transition/WXTransition.java b/android/sdk/src/main/java/com/taobao/weex/dom/transition/WXTransition.java
index 8c32c71..e59c4f7 100644
--- a/android/sdk/src/main/java/com/taobao/weex/dom/transition/WXTransition.java
+++ b/android/sdk/src/main/java/com/taobao/weex/dom/transition/WXTransition.java
@@ -32,13 +32,16 @@ import android.text.TextUtils;
 import android.util.Property;
 import android.view.View;
 import android.view.animation.Interpolator;
+
 import com.taobao.weex.WXEnvironment;
 import com.taobao.weex.WXSDKManager;
+import com.taobao.weex.bridge.WXBridgeManager;
 import com.taobao.weex.common.Constants;
-import com.taobao.weex.dom.DOMActionContext;
-import com.taobao.weex.dom.WXDomHandler;
-import com.taobao.weex.dom.WXDomObject;
-import com.taobao.weex.dom.flex.Spacing;
+//import com.taobao.weex.dom.DOMActionContext;
+//import com.taobao.weex.dom.WXDomHandler;
+//import com.taobao.weex.dom.WXDomObject;
+//import com.taobao.weex.dom.flex.Spacing;
+import com.taobao.weex.dom.CSSShorthand;
 import com.taobao.weex.ui.animation.BackgroundColorProperty;
 import com.taobao.weex.ui.animation.TransformParser;
 import com.taobao.weex.ui.component.WXComponent;
@@ -117,7 +120,7 @@ public class WXTransition {
     private Interpolator  interpolator;
     private long  duration;
     private long delay;
-    private WXDomObject domObject;
+    private WXComponent mWXComponent;
     private Handler handler;
     private ValueAnimator layoutValueAnimator;
     private Map<String, Object> layoutPendingUpdates;
@@ -142,7 +145,7 @@ public class WXTransition {
     /**
      * create transition from map styles if style contains transitionProperty
      * */
-    public static WXTransition fromMap(Map<String, Object> style, WXDomObject domObject){
+    public static WXTransition fromMap(Map<String, Object> style, WXComponent component){
         if(style.get(TRANSITION_PROPERTY) == null){
             return  null;
         }
@@ -158,11 +161,10 @@ public class WXTransition {
         transition.duration = parseTimeMillis(style, TRANSITION_DURATION, 0);
         transition.delay =  parseTimeMillis(style, TRANSITION_DELAY, 0);
         transition.interpolator = createTimeInterpolator(WXUtils.getString(style.get(TRANSITION_TIMING_FUNCTION), null));
-        transition.domObject = domObject;
+        transition.mWXComponent = component;
         return  transition;
     }
 
-
     /**
      * check updates has transition property
      * */
@@ -177,23 +179,23 @@ public class WXTransition {
 
     public void updateTranstionParams(Map<String, Object> updates){
         if(updates.containsKey(TRANSITION_DELAY)){
-            domObject.getStyles().put(TRANSITION_DELAY, updates.remove(TRANSITION_DELAY));
-            this.delay = parseTimeMillis(domObject.getStyles(), TRANSITION_DELAY, 0);
+            mWXComponent.getStyles().put(TRANSITION_DELAY, updates.remove(TRANSITION_DELAY));
+            this.delay = parseTimeMillis(mWXComponent.getStyles(), TRANSITION_DELAY, 0);
         }
 
         if(updates.containsKey(TRANSITION_TIMING_FUNCTION) && updates.get(TRANSITION_TIMING_FUNCTION) != null){
-            domObject.getStyles().put(TRANSITION_TIMING_FUNCTION, updates.remove(TRANSITION_TIMING_FUNCTION));
-            this.interpolator = createTimeInterpolator(domObject.getStyles().get(TRANSITION_TIMING_FUNCTION).toString());
+            mWXComponent.getStyles().put(TRANSITION_TIMING_FUNCTION, updates.remove(TRANSITION_TIMING_FUNCTION));
+            this.interpolator = createTimeInterpolator(mWXComponent.getStyles().get(TRANSITION_TIMING_FUNCTION).toString());
         }
 
         if(updates.containsKey(TRANSITION_DURATION)){
-            domObject.getStyles().put(TRANSITION_DURATION, updates.remove(TRANSITION_DURATION));
-            this.duration = parseTimeMillis(domObject.getStyles(), TRANSITION_DURATION, 0);
+            mWXComponent.getStyles().put(TRANSITION_DURATION, updates.remove(TRANSITION_DURATION));
+            this.duration = parseTimeMillis(mWXComponent.getStyles(), TRANSITION_DURATION, 0);
         }
 
         if(updates.containsKey(TRANSITION_PROPERTY)){
-            domObject.getStyles().put(TRANSITION_PROPERTY, updates.remove(TRANSITION_PROPERTY));
-            updateTransitionProperties(this, WXUtils.getString(domObject.getStyles().get(TRANSITION_PROPERTY), null));
+            mWXComponent.getStyles().put(TRANSITION_PROPERTY, updates.remove(TRANSITION_PROPERTY));
+            updateTransitionProperties(this, WXUtils.getString(mWXComponent.getStyles().get(TRANSITION_PROPERTY), null));
         }
     }
 
@@ -219,7 +221,7 @@ public class WXTransition {
                 }
             }
 
-            int delay = WXUtils.getNumberInt(domObject.getAttrs().get("actionDelay"), 16);
+            int delay = WXUtils.getNumberInt(mWXComponent.getAttrs().get("actionDelay"), 16);
             if(delay > duration){
                 delay = (int) duration;
             }
@@ -268,12 +270,12 @@ public class WXTransition {
                     if(targetStyles.containsKey(property)){
                         //reset pre transition style
                         Object targetValue = targetStyles.remove(property);
-                        domObject.getStyles().put(property, targetValue);
-                        WXComponent component = getComponent();
-                        if(component != null
-                                && component.getDomObject() != null){
-                            component.getDomObject().getStyles().put(property, targetValue);
-                        }
+                        mWXComponent.getStyles().put(property, targetValue);
+//                        domObject.getStyles().put(property, targetValue);
+//                        WXComponent component = getComponent();
+//                        if(component != null && component.getDomObject() != null){
+//                            component.getDomObject().getStyles().put(property, targetValue);
+//                        }
                     }
                 }
             }
@@ -292,9 +294,8 @@ public class WXTransition {
                     if(duration < Float.MIN_NORMAL){
                         return;
                     }
-                    WXComponent component = getComponent();
-                    if(component != null && domObject.getEvents().contains(Constants.Event.ON_TRANSITION_END)){
-                        component.fireEvent(Constants.Event.ON_TRANSITION_END);
+                    if(mWXComponent != null && mWXComponent.getEvents().contains(Constants.Event.ON_TRANSITION_END)){
+                        mWXComponent.fireEvent(Constants.Event.ON_TRANSITION_END);
                     }
                 }
             };
@@ -335,7 +336,7 @@ public class WXTransition {
         List<PropertyValuesHolder> holders = new ArrayList<>(8);
         String transform  = WXUtils.getString(transformPendingUpdates.remove(Constants.Name.TRANSFORM), null);
         if(!TextUtils.isEmpty(transform)){
-            Map<Property<View,Float>, Float>  properties = TransformParser.parseTransForm(transform, (int)domObject.getLayoutWidth(), (int)domObject.getLayoutHeight(), domObject.getViewPortWidth());
+            Map<Property<View,Float>, Float>  properties = TransformParser.parseTransForm(transform, (int)mWXComponent.getLayoutWidth(), (int)mWXComponent.getLayoutHeight(), mWXComponent.getViewPortWidth());
             PropertyValuesHolder[]  transformHolders = TransformParser.toHolders(properties);
             for(PropertyValuesHolder holder : transformHolders){
                 holders.add(holder);
@@ -363,7 +364,7 @@ public class WXTransition {
                 }
                 break;
                 case Constants.Name.BACKGROUND_COLOR:{
-                    int fromColor = WXResourceUtils.getColor(WXUtils.getString(domObject.getStyles().getBackgroundColor(), null), 0);
+                    int fromColor = WXResourceUtils.getColor(WXUtils.getString(mWXComponent.getStyles().getBackgroundColor(), null), 0);
                     int toColor = WXResourceUtils.getColor(WXUtils.getString(value, null), 0);
                     if(WXViewUtils.getBorderDrawable(taregtView) != null){
                         fromColor = WXViewUtils.getBorderDrawable(taregtView).getColor();
@@ -403,9 +404,6 @@ public class WXTransition {
                 }
                 super.onAnimationEnd(animation);
                 WXTransition.this.onTransitionAnimationEnd();
-                if(WXEnvironment.isApkDebugable()){
-                    WXLogUtils.d("WXTransition transform onTransitionAnimationEnd " +  domObject.getRef());
-                }
             }
         });
         transformAnimator.start();
@@ -444,73 +442,73 @@ public class WXTransition {
         PropertyValuesHolder holder = null;
         switch (property){
             case Constants.Name.WIDTH:{
-                holder = PropertyValuesHolder.ofFloat(Constants.Name.WIDTH, domObject.getLayoutWidth(),
-                        WXViewUtils.getRealPxByWidth(WXUtils.getFloat(value, 0.0f), domObject.getViewPortWidth()));
+                holder = PropertyValuesHolder.ofFloat(Constants.Name.WIDTH, mWXComponent.getLayoutWidth(),
+                        WXViewUtils.getRealPxByWidth(WXUtils.getFloat(value, 0.0f), mWXComponent.getViewPortWidth()));
             }
             break;
             case Constants.Name.HEIGHT:{
-                holder = PropertyValuesHolder.ofFloat(Constants.Name.HEIGHT, domObject.getLayoutHeight(),
-                        WXViewUtils.getRealPxByWidth(WXUtils.getFloat(value, 0.0f), domObject.getViewPortWidth()));
+                holder = PropertyValuesHolder.ofFloat(Constants.Name.HEIGHT, mWXComponent.getLayoutHeight(),
+                        WXViewUtils.getRealPxByWidth(WXUtils.getFloat(value, 0.0f), mWXComponent.getViewPortWidth()));
             }
             break;
             case Constants.Name.MARGIN_TOP:{
-                holder = PropertyValuesHolder.ofFloat(Constants.Name.MARGIN_TOP,  domObject.getMargin().get(Spacing.TOP),
-                        WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, domObject.getViewPortWidth()), domObject.getViewPortWidth()));
+                holder = PropertyValuesHolder.ofFloat(Constants.Name.MARGIN_TOP,  mWXComponent.getMargin().get(CSSShorthand.EDGE.TOP),
+                        WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, mWXComponent.getViewPortWidth()), mWXComponent.getViewPortWidth()));
             }
             break;
             case Constants.Name.MARGIN_LEFT:{
-                holder = PropertyValuesHolder.ofFloat(Constants.Name.MARGIN_LEFT,  domObject.getMargin().get(Spacing.LEFT),
-                        WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, domObject.getViewPortWidth()), domObject.getViewPortWidth()));
+                holder = PropertyValuesHolder.ofFloat(Constants.Name.MARGIN_LEFT,  mWXComponent.getMargin().get(CSSShorthand.EDGE.LEFT),
+                        WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, mWXComponent.getViewPortWidth()), mWXComponent.getViewPortWidth()));
             }
             break;
             case Constants.Name.MARGIN_RIGHT:{
-                holder = PropertyValuesHolder.ofFloat(Constants.Name.MARGIN_RIGHT,  domObject.getMargin().get(Spacing.RIGHT),
-                        WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, domObject.getViewPortWidth()), domObject.getViewPortWidth()));
+                holder = PropertyValuesHolder.ofFloat(Constants.Name.MARGIN_RIGHT,  mWXComponent.getMargin().get(CSSShorthand.EDGE.RIGHT),
+                        WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, mWXComponent.getViewPortWidth()), mWXComponent.getViewPortWidth()));
             }
             break;
             case Constants.Name.MARGIN_BOTTOM:{
-                holder = PropertyValuesHolder.ofFloat(Constants.Name.MARGIN_BOTTOM,  domObject.getMargin().get(Spacing.BOTTOM),
-                        WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, domObject.getViewPortWidth()), domObject.getViewPortWidth()));
+                holder = PropertyValuesHolder.ofFloat(Constants.Name.MARGIN_BOTTOM,  mWXComponent.getMargin().get(CSSShorthand.EDGE.BOTTOM),
+                        WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, mWXComponent.getViewPortWidth()), mWXComponent.getViewPortWidth()));
             }
             break;
             case Constants.Name.LEFT:{
-                holder = PropertyValuesHolder.ofFloat(Constants.Name.LEFT,  domObject.getPositionLeft(),
-                        WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, domObject.getViewPortWidth()), domObject.getViewPortWidth()));
+                holder = PropertyValuesHolder.ofFloat(Constants.Name.LEFT,  mWXComponent.getPadding().get(CSSShorthand.EDGE.LEFT),
+                        WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, mWXComponent.getViewPortWidth()), mWXComponent.getViewPortWidth()));
             }
             break;
             case Constants.Name.RIGHT:{
-                holder = PropertyValuesHolder.ofFloat(Constants.Name.RIGHT,  domObject.getPositionRight(),
-                        WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, domObject.getViewPortWidth()), domObject.getViewPortWidth()));
+                holder = PropertyValuesHolder.ofFloat(Constants.Name.RIGHT,  mWXComponent.getPadding().get(CSSShorthand.EDGE.RIGHT),
+                        WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, mWXComponent.getViewPortWidth()), mWXComponent.getViewPortWidth()));
             }
             break;
             case Constants.Name.BOTTOM:{
-                holder = PropertyValuesHolder.ofFloat(Constants.Name.BOTTOM,  domObject.getPositionBottom(),
-                        WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, domObject.getViewPortWidth()), domObject.getViewPortWidth()));
+                holder = PropertyValuesHolder.ofFloat(Constants.Name.BOTTOM,  mWXComponent.getPadding().get(CSSShorthand.EDGE.BOTTOM),
+                        WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, mWXComponent.getViewPortWidth()), mWXComponent.getViewPortWidth()));
             }
             break;
             case Constants.Name.TOP:{
-                holder = PropertyValuesHolder.ofFloat(Constants.Name.TOP,  domObject.getPositionTop(),
-                        WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, domObject.getViewPortWidth()), domObject.getViewPortWidth()));
+                holder = PropertyValuesHolder.ofFloat(Constants.Name.TOP,  mWXComponent.getPadding().get(CSSShorthand.EDGE.TOP),
+                        WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, mWXComponent.getViewPortWidth()), mWXComponent.getViewPortWidth()));
             }
             break;
             case Constants.Name.PADDING_TOP:{
-                holder = PropertyValuesHolder.ofFloat(Constants.Name.PADDING_TOP,  domObject.getPadding().get(Spacing.TOP),
-                        WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, domObject.getViewPortWidth()), domObject.getViewPortWidth()));
+                holder = PropertyValuesHolder.ofFloat(Constants.Name.PADDING_TOP,  mWXComponent.getPadding().get(CSSShorthand.EDGE.TOP),
+                        WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, mWXComponent.getViewPortWidth()), mWXComponent.getViewPortWidth()));
             }
             break;
             case Constants.Name.PADDING_BOTTOM:{
-                holder = PropertyValuesHolder.ofFloat(Constants.Name.PADDING_BOTTOM,  domObject.getPadding().get(Spacing.BOTTOM),
-                        WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, domObject.getViewPortWidth()), domObject.getViewPortWidth()));
+                holder = PropertyValuesHolder.ofFloat(Constants.Name.PADDING_BOTTOM,  mWXComponent.getPadding().get(CSSShorthand.EDGE.BOTTOM),
+                        WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, mWXComponent.getViewPortWidth()), mWXComponent.getViewPortWidth()));
             }
             break;
             case Constants.Name.PADDING_LEFT:{
-                holder = PropertyValuesHolder.ofFloat(Constants.Name.PADDING_LEFT,  domObject.getPadding().get(Spacing.LEFT),
-                        WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, domObject.getViewPortWidth()), domObject.getViewPortWidth()));
+                holder = PropertyValuesHolder.ofFloat(Constants.Name.PADDING_LEFT,  mWXComponent.getPadding().get(CSSShorthand.EDGE.LEFT),
+                        WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, mWXComponent.getViewPortWidth()), mWXComponent.getViewPortWidth()));
             }
             break;
             case Constants.Name.PADDING_RIGHT:{
-                holder = PropertyValuesHolder.ofFloat(Constants.Name.PADDING_RIGHT,  domObject.getPadding().get(Spacing.RIGHT),
-                        WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, domObject.getViewPortWidth()), domObject.getViewPortWidth()));
+                holder = PropertyValuesHolder.ofFloat(Constants.Name.PADDING_RIGHT,  mWXComponent.getPadding().get(CSSShorthand.EDGE.RIGHT),
+                        WXViewUtils.getRealPxByWidth(WXUtils.getFloatByViewport(value, mWXComponent.getViewPortWidth()), mWXComponent.getViewPortWidth()));
             }
             break;
             default:
@@ -526,22 +524,14 @@ public class WXTransition {
         layoutValueAnimator = ValueAnimator.ofPropertyValuesHolder(holders);
         layoutValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
             @Override
-            public void onAnimationUpdate(ValueAnimator animation) {
+            public void onAnimationUpdate(final ValueAnimator animation) {
                 PropertyValuesHolder holders[] = animation.getValues();
                 for(PropertyValuesHolder holder : holders){
-                    String property =  holder.getPropertyName();
-                    updateShadowLayoutPropertyByName(domObject,property,(Float)animation.getAnimatedValue(property));
-                }
 
-                DOMActionContext domActionContext = WXSDKManager.getInstance().getWXDomManager().getDomContext(domObject.getDomContext().getInstanceId());
-                if(domActionContext == null){
-                    return;
-                }
-                domActionContext.markDirty();
-                WXSDKManager.getInstance().getWXDomManager().sendEmptyMessageDelayed(WXDomHandler.MsgType.WX_DOM_TRANSITION_BATCH, 0);
-                if(WXEnvironment.isApkDebugable()){
-                    WXLogUtils.d("WXTransition send layout batch msg");
+                    final String property =  holder.getPropertyName();
+                    asynchronouslyUpdateLayout(mWXComponent, property, (Float) animation.getAnimatedValue(property));
                 }
+//                WXBridgeManager.getInstance().calculateLayoutPostToJSThread(mWXComponent.getInstanceId(), mWXComponent.getRef(), false);
             }
         });
         layoutValueAnimator.addListener(new AnimatorListenerAdapter() {
@@ -559,9 +549,6 @@ public class WXTransition {
                     return;
                 }
                 super.onAnimationEnd(animation);
-                if(WXEnvironment.isApkDebugable()){
-                    WXLogUtils.d("WXTransition layout onTransitionAnimationEnd " +  domObject.getRef());
-                }
                 WXTransition.this.onTransitionAnimationEnd();
             }
         });
@@ -573,89 +560,82 @@ public class WXTransition {
         layoutValueAnimator.start();
     }
 
-    private static void updateShadowLayoutPropertyByName(WXDomObject domObject, String propertyName, float propertyValue) {
-        if(domObject == null || TextUtils.isEmpty(propertyName)) {
-            return;
-        }
-        switch (propertyName){
-            case Constants.Name.WIDTH:{
-                domObject.setStyleWidth(propertyValue);
-            }
-            break;
-            case Constants.Name.HEIGHT:{
-                domObject.setStyleHeight(propertyValue);
-            }
-            break;
-            case Constants.Name.MARGIN_TOP:{
-                domObject.setMargin(Spacing.TOP, propertyValue);
-            }
-            break;
-            case Constants.Name.MARGIN_LEFT:{
-                domObject.setMargin(Spacing.LEFT, propertyValue);
-            }
-            break;
-            case Constants.Name.MARGIN_RIGHT:{
-                domObject.setMargin(Spacing.RIGHT, propertyValue);
-            }
-            break;
-            case Constants.Name.MARGIN_BOTTOM:{
-                domObject.setMargin(Spacing.BOTTOM, propertyValue);
-            }
-            break;
-            case Constants.Name.LEFT:{
-                domObject.setPositionLeft(propertyValue);
-            }
-            break;
-            case Constants.Name.RIGHT:{
-                domObject.setPositionRight(propertyValue);
-            }
-            break;
-            case Constants.Name.BOTTOM:{
-                domObject.setPositionBottom(propertyValue);
-            }
-            break;
-            case Constants.Name.TOP:{
-                domObject.setPositionTop(propertyValue);
-            }
-            break;
-            case Constants.Name.PADDING_TOP:{
-                domObject.setPadding(Spacing.TOP, propertyValue);
-            }
-            break;
-            case Constants.Name.PADDING_BOTTOM:{
-                domObject.setPadding(Spacing.BOTTOM, propertyValue);
-            }
-            break;
-            case Constants.Name.PADDING_LEFT:{
-                domObject.setPadding(Spacing.LEFT, propertyValue);
-            }
-            break;
-            case Constants.Name.PADDING_RIGHT:{
-                domObject.setPadding(Spacing.RIGHT, propertyValue);
-            }
-            break;
-            default:
-                break;
-        }
-    }
-
     @SuppressWarnings("unused")
-    public static void asynchronouslyUpdateLayout(WXComponent component, String propertyName, float propertyValue) {
-        if(component == null || TextUtils.isEmpty(propertyName)) {
-            return;
-        }
-        String instanceId = component.getInstanceId();
-        DOMActionContext domActionContext = WXSDKManager.getInstance().getWXDomManager().getDomContext(instanceId);
-        if(domActionContext == null){
+    public static void asynchronouslyUpdateLayout(WXComponent component, final String propertyName, final float propertyValue) {
+        if(component == null) {
             return;
         }
-        WXDomObject domObject = domActionContext.getDomByRef(component.getRef());
-        if(domObject == null || TextUtils.isEmpty(instanceId)) {
+        final String ref = component.getRef();
+        final String instanceId = component.getInstanceId();
+        if(TextUtils.isEmpty(ref) || TextUtils.isEmpty(instanceId)) {
             return;
         }
-        updateShadowLayoutPropertyByName(domObject, propertyName, propertyValue);
-        domActionContext.markDirty();
-        WXSDKManager.getInstance().getWXDomManager().sendEmptyMessageDelayed(WXDomHandler.MsgType.WX_DOM_TRANSITION_BATCH, 0);
+
+        WXSDKManager.getInstance().getWXBridgeManager().post(new Runnable() {
+            @Override
+            public void run() {
+                switch (propertyName){
+                    case Constants.Name.WIDTH:{
+                        WXBridgeManager.getInstance().setStyleWidth(instanceId, ref, propertyValue);
+                    }
+                    break;
+                    case Constants.Name.HEIGHT:{
+                        WXBridgeManager.getInstance().setStyleHeight(instanceId, ref, propertyValue);
+                    }
+                    break;
+                    case Constants.Name.MARGIN_TOP:{
+                        WXBridgeManager.getInstance().setMargin(instanceId, ref, CSSShorthand.EDGE.TOP, propertyValue);
+                    }
+                    break;
+                    case Constants.Name.MARGIN_LEFT:{
+                        WXBridgeManager.getInstance().setMargin(instanceId, ref, CSSShorthand.EDGE.LEFT, propertyValue);
+                    }
+                    break;
+                    case Constants.Name.MARGIN_RIGHT:{
+                        WXBridgeManager.getInstance().setMargin(instanceId, ref, CSSShorthand.EDGE.RIGHT, propertyValue);
+                    }
+                    break;
+                    case Constants.Name.MARGIN_BOTTOM:{
+                        WXBridgeManager.getInstance().setMargin(instanceId, ref, CSSShorthand.EDGE.BOTTOM, propertyValue);
+                    }
+                    break;
+                    case Constants.Name.LEFT:{
+                        WXBridgeManager.getInstance().setPosition(instanceId, ref, CSSShorthand.EDGE.LEFT, propertyValue);
+                    }
+                    break;
+                    case Constants.Name.RIGHT:{
+                        WXBridgeManager.getInstance().setPosition(instanceId, ref, CSSShorthand.EDGE.RIGHT, (propertyValue));
+                    }
+                    break;
+                    case Constants.Name.BOTTOM:{
+                        WXBridgeManager.getInstance().setPosition(instanceId, ref, CSSShorthand.EDGE.BOTTOM, propertyValue);
+                    }
+                    break;
+                    case Constants.Name.TOP:{
+                        WXBridgeManager.getInstance().setPosition(instanceId, ref, CSSShorthand.EDGE.TOP, propertyValue);
+                    }
+                    break;
+                    case Constants.Name.PADDING_TOP:{
+                        WXBridgeManager.getInstance().setPadding(instanceId, ref, CSSShorthand.EDGE.TOP, propertyValue);
+                    }
+                    break;
+                    case Constants.Name.PADDING_BOTTOM:{
+                        WXBridgeManager.getInstance().setPadding(instanceId, ref, CSSShorthand.EDGE.BOTTOM, propertyValue);
+                    }
+                    break;
+                    case Constants.Name.PADDING_LEFT:{
+                        WXBridgeManager.getInstance().setPadding(instanceId, ref, CSSShorthand.EDGE.LEFT, propertyValue);
+                    }
+                    break;
+                    case Constants.Name.PADDING_RIGHT:{
+                        WXBridgeManager.getInstance().setPadding(instanceId, ref, CSSShorthand.EDGE.RIGHT, propertyValue);
+                    }
+                    break;
+                    default:
+                        break;
+                }
+            }
+        });
     }
 
     private synchronized void onTransitionAnimationEnd(){
@@ -670,14 +650,10 @@ public class WXTransition {
         }
         synchronized (targetStyles){
             if(targetStyles.size() > 0){
-                WXComponent component = getComponent();
                 for(String property : properties) {
                     if(targetStyles.containsKey(property)){
                         Object targetValue = targetStyles.remove(property);
-                        domObject.getStyles().put(property, targetValue);
-                        if(component != null && component.getDomObject() != null){
-                            component.getDomObject().getStyles().put(property, targetValue);
-                        }
+                        mWXComponent.getStyles().put(property, targetValue);
                     }
                 }
                 targetStyles.clear();
@@ -685,33 +661,11 @@ public class WXTransition {
         }
     }
 
-    private WXComponent getComponent(){
-        DOMActionContext domActionContext = WXSDKManager.getInstance().getWXDomManager().getDomContext(domObject.getDomContext().getInstanceId());
-        if(domActionContext != null){
-            WXComponent component = domActionContext.getCompByRef(domObject.getRef());
-            return  component;
-        }
-        return null;
-    }
-
-
     private View getTargetView(){
-        if(domObject.getDomContext() == null){
-            return null;
-        }
-        DOMActionContext domActionContext = WXSDKManager.getInstance().getWXDomManager().getDomContext(domObject.getDomContext().getInstanceId());
-        if(domActionContext != null){
-            WXComponent component = domActionContext.getCompByRef(domObject.getRef());
-            if(component != null && component.getHostView() != null) {
-                return  component.getHostView();
-            }
-        }
-        return null;
+        return null != mWXComponent ? mWXComponent.getHostView() : null;
     }
 
 
-
-
     /**
      * get time millis
      * */
@@ -794,4 +748,7 @@ public class WXTransition {
         }
     }
 
+    public List<String> getProperties() {
+        return properties;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/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 a8de759..d0bcb7e 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,11 +18,7 @@
  */
 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;
 import java.util.List;
 import java.util.Map;
@@ -66,12 +62,13 @@ 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;
-        }
+        // TODO
+//        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--){

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/android/sdk/src/main/java/com/taobao/weex/el/parse/Parser.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/el/parse/Parser.java b/android/sdk/src/main/java/com/taobao/weex/el/parse/Parser.java
index 76a6eed..4ee5a9d 100644
--- a/android/sdk/src/main/java/com/taobao/weex/el/parse/Parser.java
+++ b/android/sdk/src/main/java/com/taobao/weex/el/parse/Parser.java
@@ -20,6 +20,7 @@ package com.taobao.weex.el.parse;
 
 import com.taobao.weex.WXEnvironment;
 import com.taobao.weex.utils.WXLogUtils;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -62,7 +63,7 @@ public class Parser {
     /**
      * parse code to ast block.
      * */
-    public static  Token parse(String code){
+    public static Token parse(String code){
         try{
             Parser parser = new Parser(code);
             return parser.parse();

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/android/sdk/src/main/java/com/taobao/weex/http/WXHttpUtil.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/http/WXHttpUtil.java b/android/sdk/src/main/java/com/taobao/weex/http/WXHttpUtil.java
index 7bb4b03..4f58841 100644
--- a/android/sdk/src/main/java/com/taobao/weex/http/WXHttpUtil.java
+++ b/android/sdk/src/main/java/com/taobao/weex/http/WXHttpUtil.java
@@ -31,12 +31,12 @@ import java.util.Map;
  */
 public class WXHttpUtil {
 
-  private static String sDefautUA = null;
+  private static String sDefaultUA = null;
 
   public static final String KEY_USER_AGENT = "user-agent";
 
   public static String assembleUserAgent(Context ctx,Map<String, String> config) {
-    if (TextUtils.isEmpty(sDefautUA)) {
+    if (TextUtils.isEmpty(sDefaultUA)) {
       StringBuilder builder = new StringBuilder();
       builder.append(config.get(WXConfig.sysModel))
           .append("(Android/")
@@ -60,8 +60,8 @@ public class WXHttpUtil {
           .append(TextUtils.isEmpty(config.get(WXConfig.externalUserAgent)) ? "" : " ")
 
           .append(WXViewUtils.getScreenWidth(ctx) + "x" + WXViewUtils.getScreenHeight(ctx));
-      sDefautUA = builder.toString();
+      sDefaultUA = builder.toString();
     }
-    return sDefautUA;
+    return sDefaultUA;
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/android/sdk/src/main/java/com/taobao/weex/http/WXStreamModule.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/http/WXStreamModule.java b/android/sdk/src/main/java/com/taobao/weex/http/WXStreamModule.java
index e3ac2f0..7028698 100644
--- a/android/sdk/src/main/java/com/taobao/weex/http/WXStreamModule.java
+++ b/android/sdk/src/main/java/com/taobao/weex/http/WXStreamModule.java
@@ -55,7 +55,7 @@ public class WXStreamModule extends WXModule {
     this(null);
   }
   public WXStreamModule(IWXHttpAdapter adapter){
-   mAdapter = adapter;
+    mAdapter = adapter;
   }
 
   /**
@@ -93,10 +93,10 @@ public class WXStreamModule extends WXModule {
       public void onResponse(WXResponse response, Map<String, String> headers) {
         if(callback != null && mWXSDKInstance != null)
           WXBridgeManager.getInstance().callback(mWXSDKInstance.getInstanceId(), callback,
-            (response == null || response.originalData == null) ? "{}" :
-              readAsString(response.originalData,
-                headers!=null?getHeader(headers,"Content-Type"):""
-              ));
+                  (response == null || response.originalData == null) ? "{}" :
+                          readAsString(response.originalData,
+                                  headers!=null?getHeader(headers,"Content-Type"):""
+                          ));
       }
     }, null);
   }
@@ -269,11 +269,11 @@ public class WXStreamModule extends WXModule {
     wxRequest.instanceId = mWXSDKInstance.getInstanceId();
 
     if(options.getHeaders()!=null)
-    if (wxRequest.paramMap == null) {
-      wxRequest.paramMap = options.getHeaders();
-    }else{
-      wxRequest.paramMap.putAll(options.getHeaders());
-    }
+      if (wxRequest.paramMap == null) {
+        wxRequest.paramMap = options.getHeaders();
+      }else{
+        wxRequest.paramMap.putAll(options.getHeaders());
+      }
 
 
     IWXHttpAdapter adapter = ( mAdapter==null && mWXSDKInstance != null) ? mWXSDKInstance.getWXHttpAdapter() : mAdapter;

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/android/sdk/src/main/java/com/taobao/weex/layout/ContentBoxMeasurement.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/layout/ContentBoxMeasurement.java b/android/sdk/src/main/java/com/taobao/weex/layout/ContentBoxMeasurement.java
new file mode 100644
index 0000000..d25a845
--- /dev/null
+++ b/android/sdk/src/main/java/com/taobao/weex/layout/ContentBoxMeasurement.java
@@ -0,0 +1,78 @@
+/**
+ * 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.layout;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import com.taobao.weex.base.CalledByNative;
+import com.taobao.weex.common.Destroyable;
+import com.taobao.weex.ui.component.WXComponent;
+
+import java.io.Serializable;
+import java.lang.ref.WeakReference;
+
+public abstract class ContentBoxMeasurement implements Serializable,Destroyable {
+
+  @Nullable
+  protected WXComponent mComponent;
+
+  protected float mMeasureWidth;
+
+  protected float mMeasureHeight;
+
+  public ContentBoxMeasurement() {
+    mComponent = null;
+  }
+
+  public ContentBoxMeasurement(@NonNull WXComponent component) {
+    this.mComponent = component;
+  }
+
+  /** uiThread = false **/
+  @CalledByNative
+  public final void measure(float width, float height, int widthMeasureMode, int heightMeasureMode) {
+    measureInternal(width, height, widthMeasureMode, heightMeasureMode);
+  }
+
+  /** uiThread = false **/
+  public abstract void measureInternal(float width, float height, int widthMeasureMode, int heightMeasureMode);
+
+  /** uiThread = false **/
+  @CalledByNative
+  public abstract void layoutBefore();
+
+  /** uiThread = false **/
+  @CalledByNative
+  public abstract void layoutAfter(float computedWidth, float computedHeight);
+
+  @CalledByNative
+  public float getWidth() {
+    return mMeasureWidth;
+  }
+
+  @CalledByNative
+  public float getHeight() {
+    return mMeasureHeight;
+  }
+
+  @Override
+  public void destroy() {
+    mComponent = null;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/android/sdk/src/main/java/com/taobao/weex/layout/MeasureMode.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/layout/MeasureMode.java b/android/sdk/src/main/java/com/taobao/weex/layout/MeasureMode.java
new file mode 100644
index 0000000..68670ba
--- /dev/null
+++ b/android/sdk/src/main/java/com/taobao/weex/layout/MeasureMode.java
@@ -0,0 +1,40 @@
+/**
+ * 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.layout;
+
+import com.taobao.weex.base.CalledByNative;
+
+import java.io.Serializable;
+
+public class MeasureMode implements Serializable {
+
+  public static int EXACTLY = 0;
+
+  public static int UNSPECIFIED = 1;
+
+  @CalledByNative
+  public static int getEXACTLY() {
+    return EXACTLY;
+  }
+
+  @CalledByNative
+  public static int getUNSPECIFIED() {
+    return UNSPECIFIED;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/android/sdk/src/main/java/com/taobao/weex/layout/MeasureSize.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/layout/MeasureSize.java b/android/sdk/src/main/java/com/taobao/weex/layout/MeasureSize.java
new file mode 100644
index 0000000..ad671bf
--- /dev/null
+++ b/android/sdk/src/main/java/com/taobao/weex/layout/MeasureSize.java
@@ -0,0 +1,42 @@
+/**
+ * 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.layout;
+
+import java.io.Serializable;
+
+public class MeasureSize implements Serializable{
+  private float width;
+  private float height;
+
+  public float getWidth() {
+    return width;
+  }
+
+  public void setWidth(float width) {
+    this.width = width;
+  }
+
+  public float getHeight() {
+    return height;
+  }
+
+  public void setHeight(float height) {
+    this.height = height;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/android/sdk/src/main/java/com/taobao/weex/layout/measurefunc/TextContentBoxMeasurement.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/layout/measurefunc/TextContentBoxMeasurement.java b/android/sdk/src/main/java/com/taobao/weex/layout/measurefunc/TextContentBoxMeasurement.java
new file mode 100644
index 0000000..2a5ba3f
--- /dev/null
+++ b/android/sdk/src/main/java/com/taobao/weex/layout/measurefunc/TextContentBoxMeasurement.java
@@ -0,0 +1,472 @@
+/**
+ * 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.layout.measurefunc;
+
+import android.graphics.Canvas;
+import android.os.Build;
+import android.os.Looper;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.text.Editable;
+import android.text.Layout;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.SpannableStringBuilder;
+import android.text.Spanned;
+import android.text.SpannedString;
+import android.text.StaticLayout;
+import android.text.TextPaint;
+import android.text.TextUtils;
+import android.text.style.AbsoluteSizeSpan;
+import android.text.style.AlignmentSpan;
+import android.text.style.ForegroundColorSpan;
+
+import com.taobao.weex.common.Constants;
+import com.taobao.weex.dom.TextDecorationSpan;
+import com.taobao.weex.dom.WXAttr;
+import com.taobao.weex.dom.WXCustomStyleSpan;
+import com.taobao.weex.dom.WXLineHeightSpan;
+import com.taobao.weex.dom.WXStyle;
+import com.taobao.weex.layout.ContentBoxMeasurement;
+import com.taobao.weex.layout.MeasureMode;
+import com.taobao.weex.layout.MeasureSize;
+import com.taobao.weex.ui.component.WXComponent;
+import com.taobao.weex.ui.component.WXText;
+import com.taobao.weex.ui.component.WXTextDecoration;
+import com.taobao.weex.utils.WXDomUtils;
+import com.taobao.weex.utils.WXLogUtils;
+import com.taobao.weex.utils.WXResourceUtils;
+
+import java.lang.ref.WeakReference;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
+
+import static com.taobao.weex.dom.WXStyle.UNSET;
+import static com.taobao.weex.utils.WXUtils.isUndefined;
+
+/**
+ * Created by miomin on 2018/3/9.
+ */
+
+public class TextContentBoxMeasurement extends ContentBoxMeasurement {
+
+  private static final Canvas DUMMY_CANVAS = new Canvas();
+
+  public TextContentBoxMeasurement(WXComponent component) {
+    super(component);
+  }
+
+  class SetSpanOperation {
+
+    protected final int start, end, flag;
+    protected final Object what;
+
+    SetSpanOperation(int start, int end, Object what) {
+      this(start, end, what, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+    }
+
+    SetSpanOperation(int start, int end, Object what, int flag) {
+      this.start = start;
+      this.end = end;
+      this.what = what;
+      this.flag = flag;
+    }
+
+    public void execute(Spannable sb) {
+      sb.setSpan(what, start, end, flag);
+    }
+  }
+
+  private static final String ELLIPSIS = "\u2026";
+  private boolean mIsColorSet = false;
+  private boolean hasBeenMeasured = false;
+  private int mColor;
+  private int mFontStyle = UNSET;
+  private int mFontWeight = UNSET;
+  private int mNumberOfLines = UNSET;
+  private int mFontSize = UNSET;
+  private int mLineHeight = UNSET;
+  private float previousWidth = Float.NaN;
+  private String mFontFamily = null;
+  private String mText = null;
+  private TextUtils.TruncateAt textOverflow;
+  private Layout.Alignment mAlignment;
+  private WXTextDecoration mTextDecoration = WXTextDecoration.NONE;
+  private TextPaint mTextPaint;
+  private @Nullable
+  Spanned spanned;
+  private @Nullable
+  Layout layout;
+  private AtomicReference<Layout> atomicReference = new AtomicReference<>();
+
+  /**
+   * uiThread = false
+   **/
+  @Override
+  public void layoutBefore() {
+    mTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
+    hasBeenMeasured = false;
+    updateStyleAndText();
+    spanned = createSpanned(mText);
+  }
+
+  /**
+   * uiThread = false
+   **/
+  @Override
+  public void measureInternal(float width, float height, int widthMeasureMode, int heightMeasureMode) {
+    float measureWidth = width, measureHeight = height;
+    hasBeenMeasured = true;
+    float textWidth = getTextWidth(mTextPaint, width, widthMeasureMode == MeasureMode.EXACTLY);
+
+    if (textWidth > 0 && mText != null) {
+      layout = createLayout(textWidth,null);
+      previousWidth = layout.getWidth();
+      if (Float.isNaN(width)) {
+        measureWidth = layout.getWidth();
+      } else {
+        measureWidth = Math.min(layout.getWidth(), measureWidth);
+      }
+
+      if (Float.isNaN(height)) {
+        measureHeight = layout.getHeight();
+      }
+    } else {
+      if (widthMeasureMode == MeasureMode.UNSPECIFIED) {
+        measureWidth = 0;
+      }
+      if (heightMeasureMode == MeasureMode.UNSPECIFIED) {
+        measureHeight = 0;
+      }
+    }
+    mMeasureWidth = measureWidth;
+    mMeasureHeight = measureHeight;
+  }
+
+  /**
+   * uiThread = false
+   **/
+  @Override
+  public void layoutAfter(float computedWidth, float computedHeight) {
+    if (hasBeenMeasured) {
+      if (layout != null &&
+              WXDomUtils.getContentWidth(mComponent.getPadding(), mComponent.getBorder(), computedWidth)
+                      != previousWidth) {
+        recalculateLayout(computedWidth);
+      }
+    } else {
+      updateStyleAndText();
+      recalculateLayout(computedWidth);
+    }
+    hasBeenMeasured = false;
+    if (layout != null && !layout.equals(atomicReference.get()) &&
+            Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+      if (Thread.currentThread() != Looper.getMainLooper().getThread()) {
+        warmUpTextLayoutCache(layout);
+      }
+    }
+    swap();
+    mComponent.getInstance().runOnUiThread(new Runnable() {
+      @Override
+      public void run() {
+        mComponent.updateExtra(atomicReference.get());
+      }
+    });
+  }
+
+  private void updateStyleAndText() {
+    updateStyleImp(mComponent.getStyles());
+    mText = WXAttr.getValue(mComponent.getAttrs());
+  }
+
+  /**
+   * Record the property according to the given style
+   *
+   * @param style the give style.
+   */
+  private void updateStyleImp(Map<String, Object> style) {
+    if (style != null) {
+      if (style.containsKey(Constants.Name.LINES)) {
+        int lines = WXStyle.getLines(style);
+        mNumberOfLines = lines > 0 ? lines : UNSET;
+      }
+      if (style.containsKey(Constants.Name.FONT_SIZE)) {
+        mFontSize = WXStyle.getFontSize(style, mComponent.getViewPortWidth());
+      }
+      if (style.containsKey(Constants.Name.FONT_WEIGHT)) {
+        mFontWeight = WXStyle.getFontWeight(style);
+      }
+      if (style.containsKey(Constants.Name.FONT_STYLE)) {
+        mFontStyle = WXStyle.getFontStyle(style);
+      }
+      if (style.containsKey(Constants.Name.COLOR)) {
+        mColor = WXResourceUtils.getColor(WXStyle.getTextColor(style));
+        mIsColorSet = mColor != Integer.MIN_VALUE;
+      }
+      if (style.containsKey(Constants.Name.TEXT_DECORATION)) {
+        mTextDecoration = WXStyle.getTextDecoration(style);
+      }
+      if (style.containsKey(Constants.Name.FONT_FAMILY)) {
+        mFontFamily = WXStyle.getFontFamily(style);
+      }
+      mAlignment = WXStyle.getTextAlignment(style);
+      textOverflow = WXStyle.getTextOverflow(style);
+      int lineHeight = WXStyle.getLineHeight(style, mComponent.getViewPortWidth());
+      if (lineHeight != UNSET) {
+        mLineHeight = lineHeight;
+      }
+    }
+  }
+
+  /**
+   * Update {@link #spanned} according to the give charSequence and styles
+   *
+   * @param text the give raw text.
+   * @return an Spanned contains text and spans
+   */
+  protected
+  @NonNull
+  Spanned createSpanned(String text) {
+    if (!TextUtils.isEmpty(text)) {
+      SpannableString spannable = new SpannableString(text);
+      updateSpannable(spannable, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+      return spannable;
+    }
+    return new SpannableString("");
+  }
+
+  protected void updateSpannable(Spannable spannable, int spanFlag) {
+    int end = spannable.length();
+    if (mFontSize == UNSET) {
+      setSpan(spannable, new AbsoluteSizeSpan(WXText.sDEFAULT_SIZE), 0, end, spanFlag);
+    }
+    else{
+      setSpan(spannable,  new AbsoluteSizeSpan(mFontSize), 0, end, spanFlag);
+    }
+
+    if (mLineHeight != UNSET) {
+      setSpan(spannable, new WXLineHeightSpan(mLineHeight), 0, end, spanFlag);
+    }
+
+    setSpan(spannable, new AlignmentSpan.Standard(mAlignment), 0, end, spanFlag);
+
+    if (mFontStyle != UNSET || mFontWeight != UNSET || mFontFamily != null) {
+      setSpan(spannable, new WXCustomStyleSpan(mFontStyle, mFontWeight, mFontFamily), 0, end, spanFlag);
+    }
+
+    if (mIsColorSet) {
+      setSpan(spannable, new ForegroundColorSpan(mColor), 0, end, spanFlag);
+    }
+
+    if (mTextDecoration == WXTextDecoration.UNDERLINE || mTextDecoration == WXTextDecoration.LINETHROUGH) {
+      setSpan(spannable, new TextDecorationSpan(mTextDecoration), 0, end, spanFlag);
+    }
+  }
+
+  private void setSpan(Spannable spannable, Object what, int start, int end, int spanFlag){
+    spannable.setSpan(what, start, end, spanFlag);
+  }
+
+  /**
+   * Get text width according to constrain of outerWidth with and forceToDesired
+   *
+   * @param textPaint      paint used to measure text
+   * @param outerWidth     the width that css-layout desired.
+   * @param forceToDesired if set true, the return value will be outerWidth, no matter what the width
+   *                       of text is.
+   * @return if forceToDesired is false, it will be the minimum value of the width of text and
+   * outerWidth in case of outerWidth is defined, in other case, it will be outer width.
+   */
+  private float getTextWidth(TextPaint textPaint, float outerWidth, boolean forceToDesired) {
+    if (mText == null) {
+      if (forceToDesired) {
+        return outerWidth;
+      }
+      return 0;
+    }
+    else {
+      float textWidth;
+      if (forceToDesired) {
+        textWidth = outerWidth;
+      } else {
+        float desiredWidth = Layout.getDesiredWidth(spanned, textPaint);
+        if (isUndefined(outerWidth) || desiredWidth < outerWidth) {
+          textWidth = desiredWidth;
+        } else {
+          textWidth = outerWidth;
+        }
+      }
+      return textWidth;
+    }
+  }
+
+  /**
+   * Update layout according to {@link #mText} and span
+   *
+   * @param width          the specified width.
+   * @param forceWidth     If true, force the text width to the specified width, otherwise, text width
+   *                       may equals to or be smaller than the specified width.
+   * @param previousLayout the result of previous layout, could be null.
+   */
+  private
+  @NonNull
+  Layout createLayout(final float textWidth, @Nullable Layout previousLayout) {
+    Layout layout;
+    if (previousWidth != textWidth || previousLayout == null) {
+      layout = new StaticLayout(spanned, mTextPaint, (int) Math.ceil(textWidth),
+              Layout.Alignment.ALIGN_NORMAL, 1, 0, false);
+    } else {
+      layout = previousLayout;
+    }
+    if (mNumberOfLines != UNSET && mNumberOfLines > 0 && mNumberOfLines < layout.getLineCount()) {
+      int lastLineStart, lastLineEnd;
+      lastLineStart = layout.getLineStart(mNumberOfLines - 1);
+      lastLineEnd = layout.getLineEnd(mNumberOfLines - 1);
+      if (lastLineStart < lastLineEnd) {
+        SpannableStringBuilder builder = null;
+        if (lastLineStart > 0) {
+          builder = new SpannableStringBuilder(spanned.subSequence(0, lastLineStart));
+        } else {
+          builder = new SpannableStringBuilder();
+        }
+        Editable lastLine = new SpannableStringBuilder(spanned.subSequence(lastLineStart, lastLineEnd));
+        builder.append(truncate(lastLine, mTextPaint, (int) Math.ceil(textWidth), textOverflow));
+        adjustSpansRange(spanned, builder);
+        spanned = builder;
+        return new StaticLayout(spanned, mTextPaint, (int) Math.ceil(textWidth),
+                Layout.Alignment.ALIGN_NORMAL, 1, 0, false);
+      }
+    }
+    return layout;
+  }
+
+  /**
+   * Truncate the source span to the specified lines.
+   * Caller of this method must ensure that the lines of text is <strong>greater than desired lines and need truncate</strong>.
+   * Otherwise, unexpected behavior may happen.
+   *
+   * @param source     The source span.
+   * @param paint      the textPaint
+   * @param desired    specified lines.
+   * @param truncateAt truncate method, null value means clipping overflow text directly, non-null value means using ellipsis strategy to clip
+   * @return The spans after clipped.
+   */
+  private
+  @NonNull
+  Spanned truncate(@Nullable Editable source, @NonNull TextPaint paint,
+                   int desired, @Nullable TextUtils.TruncateAt truncateAt) {
+    Spanned ret = new SpannedString("");
+    if (!TextUtils.isEmpty(source) && source.length() > 0) {
+      if (truncateAt != null) {
+        source.append(ELLIPSIS);
+        Object[] spans = source.getSpans(0, source.length(), Object.class);
+        for (Object span : spans) {
+          int start = source.getSpanStart(span);
+          int end = source.getSpanEnd(span);
+          if (start == 0 && end == source.length() - 1) {
+            source.removeSpan(span);
+            source.setSpan(span, 0, source.length(), source.getSpanFlags(span));
+          }
+        }
+      }
+
+      StaticLayout layout;
+      int startOffset;
+
+      while (source.length() > 1) {
+        startOffset = source.length() - 1;
+        if (truncateAt != null) {
+          startOffset -= 1;
+        }
+        source.delete(startOffset, startOffset + 1);
+        layout = new StaticLayout(source, paint, desired, Layout.Alignment.ALIGN_NORMAL, 1, 0, false);
+        if (layout.getLineCount() <= 1) {
+          ret = source;
+          break;
+        }
+      }
+    }
+    return ret;
+  }
+
+  /**
+   * Adjust span range after truncate due to the wrong span range during span copy and slicing.
+   *
+   * @param beforeTruncate The span before truncate
+   * @param afterTruncate  The span after truncate
+   */
+  private void adjustSpansRange(@NonNull Spanned beforeTruncate, @NonNull Spannable afterTruncate) {
+    Object[] spans = beforeTruncate.getSpans(0, beforeTruncate.length(), Object.class);
+    for (Object span : spans) {
+      int start = beforeTruncate.getSpanStart(span);
+      int end = beforeTruncate.getSpanEnd(span);
+      if (start == 0 && end == beforeTruncate.length()) {
+        afterTruncate.removeSpan(span);
+        afterTruncate.setSpan(span, 0, afterTruncate.length(), beforeTruncate.getSpanFlags(span));
+      }
+    }
+  }
+
+  private void recalculateLayout(float computedWidth) {
+    float contentWidth = WXDomUtils.getContentWidth(mComponent.getPadding(), mComponent.getBorder(), computedWidth);
+    if (contentWidth > 0) {
+      spanned = createSpanned(mText);
+      if (mText != null) {
+        layout = createLayout(contentWidth, layout);
+        previousWidth = layout.getWidth();
+      } else {
+        previousWidth = 0;
+      }
+    }
+  }
+
+  /**
+   * As warming up TextLayoutCache done in the DOM thread may manipulate UI operation,
+   * there may be some exception, in which case the exception is ignored. After all,
+   * this is just a warm up operation.
+   *
+   * @return false for warm up failure, otherwise returns true.
+   */
+  private boolean warmUpTextLayoutCache(Layout layout) {
+    boolean result;
+    try {
+      layout.draw(DUMMY_CANVAS);
+      result = true;
+    } catch (Exception e) {
+      WXLogUtils.eTag("TextWarmUp", e);
+      result = false;
+    }
+    return result;
+  }
+
+  /**
+   * Move the reference of current layout to the {@link AtomicReference} for further use,
+   * then clear current layout.
+   */
+  private void swap() {
+    if (layout != null) {
+      atomicReference.set(layout);
+      layout = null;
+    }
+    hasBeenMeasured = false;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/android/sdk/src/main/java/com/taobao/weex/performance/WXAnalyzerDataTransfer.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/performance/WXAnalyzerDataTransfer.java b/android/sdk/src/main/java/com/taobao/weex/performance/WXAnalyzerDataTransfer.java
index 129dcec..27c75f8 100644
--- a/android/sdk/src/main/java/com/taobao/weex/performance/WXAnalyzerDataTransfer.java
+++ b/android/sdk/src/main/java/com/taobao/weex/performance/WXAnalyzerDataTransfer.java
@@ -67,11 +67,11 @@ public class WXAnalyzerDataTransfer {
       }
 
       data = new JSONObject()
-          .put("instanceId", instanceId)
-          .put("url", instance.getBundleUrl())
-          .put("dimensionMap", dimensionMap)
-          .put("measureMap", measureMap)
-          .toString();
+              .put("instanceId", instanceId)
+              .put("url", instance.getBundleUrl())
+              .put("dimensionMap", dimensionMap)
+              .put("measureMap", measureMap)
+              .toString();
 
     } catch (Exception e) {
       e.printStackTrace();
@@ -98,12 +98,12 @@ public class WXAnalyzerDataTransfer {
     String data = "";
     try {
       data = new JSONObject()
-          .put("instanceId", instanceId)
-          .put("url", instance.getBundleUrl())
-          .put("errorCode", errorCode.getErrorCode())
-          .put("errorMsg", errorCode.getErrorMsg())
-          .put("errorGroup", errorCode.getErrorGroup())
-          .toString();
+              .put("instanceId", instanceId)
+              .put("url", instance.getBundleUrl())
+              .put("errorCode", errorCode.getErrorCode())
+              .put("errorMsg", errorCode.getErrorMsg())
+              .put("errorGroup", errorCode.getErrorGroup())
+              .toString();
     } catch (Exception e) {
       e.printStackTrace();
     }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/android/sdk/src/main/java/com/taobao/weex/tracing/WXTracing.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/tracing/WXTracing.java b/android/sdk/src/main/java/com/taobao/weex/tracing/WXTracing.java
index da1fc4f..0dc11ce 100644
--- a/android/sdk/src/main/java/com/taobao/weex/tracing/WXTracing.java
+++ b/android/sdk/src/main/java/com/taobao/weex/tracing/WXTracing.java
@@ -39,7 +39,7 @@ public class WXTracing {
   public static int nextId() {
     return sIdGenerator.getAndIncrement();
   }
-  
+
   public static boolean isAvailable() {
     return WXEnvironment.isApkDebugable();
   }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/android/sdk/src/main/java/com/taobao/weex/ui/ComponentCreator.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/ComponentCreator.java b/android/sdk/src/main/java/com/taobao/weex/ui/ComponentCreator.java
index eee2b42..c2e7f15 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/ComponentCreator.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/ComponentCreator.java
@@ -19,7 +19,7 @@
 package com.taobao.weex.ui;
 
 import com.taobao.weex.WXSDKInstance;
-import com.taobao.weex.dom.WXDomObject;
+import com.taobao.weex.ui.action.BasicComponentData;
 import com.taobao.weex.ui.component.WXComponent;
 import com.taobao.weex.ui.component.WXVContainer;
 
@@ -29,5 +29,5 @@ import java.lang.reflect.InvocationTargetException;
  * Created by sospartan on 7/27/16.
  */
 public interface ComponentCreator {
-  WXComponent createInstance(WXSDKInstance instance, WXDomObject node, WXVContainer parent) throws IllegalAccessException, InvocationTargetException, InstantiationException;
+  WXComponent createInstance(WXSDKInstance instance, WXVContainer parent, BasicComponentData basicComponentData) throws IllegalAccessException, InvocationTargetException, InstantiationException;
 }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/android/sdk/src/main/java/com/taobao/weex/ui/ExternalLoaderComponentHolder.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/ExternalLoaderComponentHolder.java b/android/sdk/src/main/java/com/taobao/weex/ui/ExternalLoaderComponentHolder.java
index fb487dc..312a538 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/ExternalLoaderComponentHolder.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/ExternalLoaderComponentHolder.java
@@ -22,7 +22,7 @@ import android.util.Pair;
 
 import com.taobao.weex.WXSDKInstance;
 import com.taobao.weex.bridge.Invoker;
-import com.taobao.weex.dom.WXDomObject;
+import com.taobao.weex.ui.action.BasicComponentData;
 import com.taobao.weex.ui.component.WXComponent;
 import com.taobao.weex.ui.component.WXVContainer;
 
@@ -42,7 +42,7 @@ public class ExternalLoaderComponentHolder implements IFComponentHolder {
   private Class mClass;
 
 
-  public ExternalLoaderComponentHolder(String type, IExternalComponentGetter clzGetter) {
+  public ExternalLoaderComponentHolder(String type,IExternalComponentGetter clzGetter) {
     this.mClzGetter = clzGetter;
     mType = type;
   }
@@ -62,15 +62,13 @@ public class ExternalLoaderComponentHolder implements IFComponentHolder {
     return true;
   }
 
-
-
   @Override
-  public synchronized WXComponent createInstance(WXSDKInstance instance, WXDomObject node, WXVContainer parent) throws IllegalAccessException, InvocationTargetException, InstantiationException {
-    if(mClass == null){
-      mClass = mClzGetter.getExternalComponentClass(mType,instance);
+  public synchronized WXComponent createInstance(WXSDKInstance instance, WXVContainer parent, BasicComponentData basicComponentData) throws IllegalAccessException, InvocationTargetException, InstantiationException {
+    if (mClass == null) {
+      mClass = mClzGetter.getExternalComponentClass(mType, instance);
     }
     ComponentCreator creator = new SimpleComponentHolder.ClazzComponentCreator(mClass);
-    WXComponent component = creator.createInstance(instance,node,parent);
+    WXComponent component = creator.createInstance(instance, parent, basicComponentData);
 
     component.bindHolder(this);
     return component;

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/android/sdk/src/main/java/com/taobao/weex/ui/IWXRenderTask.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/IWXRenderTask.java b/android/sdk/src/main/java/com/taobao/weex/ui/IWXRenderTask.java
deleted file mode 100644
index efe0d3e..0000000
--- a/android/sdk/src/main/java/com/taobao/weex/ui/IWXRenderTask.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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;
-
-import com.taobao.weex.common.IWXTask;
-
-public interface IWXRenderTask extends IWXTask {
-
-  void execute();
-}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/android/sdk/src/main/java/com/taobao/weex/ui/RenderActionContextImpl.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/RenderActionContextImpl.java b/android/sdk/src/main/java/com/taobao/weex/ui/RenderActionContextImpl.java
deleted file mode 100644
index e439022..0000000
--- a/android/sdk/src/main/java/com/taobao/weex/ui/RenderActionContextImpl.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * 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;
-
-import android.graphics.Rect;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-
-import com.alibaba.fastjson.JSONObject;
-import com.taobao.weex.WXSDKInstance;
-import com.taobao.weex.bridge.JSCallback;
-import com.taobao.weex.common.WXRenderStrategy;
-import com.taobao.weex.dom.WXDomObject;
-import com.taobao.weex.dom.flex.Spacing;
-import com.taobao.weex.dom.RenderActionContext;
-import com.taobao.weex.ui.animation.WXAnimationBean;
-import com.taobao.weex.ui.animation.WXAnimationModule;
-import com.taobao.weex.ui.component.Scrollable;
-import com.taobao.weex.ui.component.WXComponent;
-import com.taobao.weex.ui.component.WXComponentFactory;
-import com.taobao.weex.ui.component.WXVContainer;
-import com.taobao.weex.utils.WXViewUtils;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Class for rendering view. Method in this class should be run in main thread.
- * This class is also <strong>not</storng> thread safe.
- * This class is very similar to {@link com.taobao.weex.dom.WXDomStatement}
- * @see com.taobao.weex.dom.WXDomStatement
- */
-class RenderActionContextImpl implements RenderActionContext {
-
-  private Map<String, WXComponent> mRegistry;
-  private WXSDKInstance mWXSDKInstance;
-  /**
-   * The container for weex root view.
-   */
-
-  public RenderActionContextImpl(WXSDKInstance instance) {
-    mWXSDKInstance = instance;
-    mRegistry = new HashMap<>();
-  }
-
-  /**
-   * @see com.taobao.weex.dom.WXDomStatement#destroy()
-   */
-  public void destroy() {
-    mWXSDKInstance = null;
-    mRegistry.clear();
-  }
-
-  public WXSDKInstance getWXSDKInstance() {
-    return mWXSDKInstance;
-  }
-
-  /**
-   * set layout information of View
-   */
-  void setLayout(String ref, WXDomObject domObject) {
-    WXComponent component = mRegistry.get(ref);
-    if (component == null) {
-      return;
-    }
-    component.setLayout(domObject);
-  }
-
-  /**
-   * set extra information of View
-   */
-  void setExtra(String ref, Object extra) {
-    WXComponent component = mRegistry.get(ref);
-    if (component == null) {
-      return;
-    }
-    component.updateExtra(extra);
-  }
-
-  @Override
-  public WXSDKInstance getInstance() {
-    return mWXSDKInstance;
-  }
-
-  @Override
-  public WXComponent getComponent(String ref) {
-    return mRegistry.get(ref);
-  }
-
-  public void registerComponent(String ref, WXComponent comp) {
-    mRegistry.put(ref,comp);
-  }
-
-  public WXComponent unregisterComponent(String ref) {
-    return mRegistry.remove(ref);
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/android/sdk/src/main/java/com/taobao/weex/ui/RenderContextImpl.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/RenderContextImpl.java b/android/sdk/src/main/java/com/taobao/weex/ui/RenderContextImpl.java
new file mode 100644
index 0000000..c63bc2b
--- /dev/null
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/RenderContextImpl.java
@@ -0,0 +1,75 @@
+/*
+ * 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;
+
+import android.support.v4.util.ArrayMap;
+import android.util.Log;
+
+import com.taobao.weex.WXSDKInstance;
+import com.taobao.weex.dom.RenderContext;
+import com.taobao.weex.ui.component.WXComponent;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Class for rendering view. Method in this class should be run in main thread.
+ * This class is also <strong>not</storng> thread safe.
+ */
+class RenderContextImpl implements RenderContext {
+
+  private Map<String, WXComponent> mRegistry;
+  private WXSDKInstance mWXSDKInstance;
+
+  public RenderContextImpl(WXSDKInstance instance) {
+    mWXSDKInstance = instance;
+    mRegistry = new ArrayMap<>();
+  }
+
+  public void destroy() {
+    mWXSDKInstance = null;
+    mRegistry.clear();
+  }
+
+  public WXSDKInstance getWXSDKInstance() {
+    return mWXSDKInstance;
+  }
+
+  @Override
+  public WXSDKInstance getInstance() {
+    return mWXSDKInstance;
+  }
+
+  @Override
+  public WXComponent getComponent(String ref) {
+    return mRegistry.get(ref);
+  }
+
+  public void registerComponent(String ref, WXComponent comp) {
+    mRegistry.put(ref, comp);
+  }
+
+  public WXComponent unregisterComponent(String ref) {
+    return mRegistry.remove(ref);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/android/sdk/src/main/java/com/taobao/weex/ui/SimpleComponentHolder.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/SimpleComponentHolder.java b/android/sdk/src/main/java/com/taobao/weex/ui/SimpleComponentHolder.java
index cfbe2be..9743582 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/SimpleComponentHolder.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/SimpleComponentHolder.java
@@ -27,7 +27,7 @@ import com.taobao.weex.bridge.Invoker;
 import com.taobao.weex.bridge.MethodInvoker;
 import com.taobao.weex.annotation.Component;
 import com.taobao.weex.common.WXRuntimeException;
-import com.taobao.weex.dom.WXDomObject;
+import com.taobao.weex.ui.action.BasicComponentData;
 import com.taobao.weex.ui.component.WXComponent;
 import com.taobao.weex.ui.component.WXComponentProp;
 import com.taobao.weex.ui.component.WXVContainer;
@@ -60,20 +60,20 @@ public class SimpleComponentHolder implements IFComponentHolder{
       mCompClz = c;
     }
 
-    private void loadConstructor(){
+    private void loadConstructor() {
       Class<? extends WXComponent> c = mCompClz;
       Constructor<? extends WXComponent> constructor;
       try {
-        constructor = c.getConstructor(WXSDKInstance.class, WXDomObject.class, WXVContainer.class);
+        constructor = c.getConstructor(WXSDKInstance.class, WXVContainer.class, BasicComponentData.class);
       } catch (NoSuchMethodException e) {
-        WXLogUtils.d("ClazzComponentCreator","Use deprecated component constructor");
+        WXLogUtils.d("ClazzComponentCreator", "Use deprecated component constructor");
         try {
           //compatible deprecated constructor with 4 args
-          constructor = c.getConstructor(WXSDKInstance.class, WXDomObject.class, WXVContainer.class, boolean.class);
+          constructor = c.getConstructor(WXSDKInstance.class, WXVContainer.class, boolean.class, BasicComponentData.class);
         } catch (NoSuchMethodException e1) {
           try {
             //compatible deprecated constructor with 5 args
-            constructor = c.getConstructor(WXSDKInstance.class, WXDomObject.class, WXVContainer.class,String.class, boolean.class);
+            constructor = c.getConstructor(WXSDKInstance.class, WXVContainer.class, String.class, boolean.class, BasicComponentData.class);
           } catch (NoSuchMethodException e2) {
             throw new WXRuntimeException("Can't find constructor of component.");
           }
@@ -83,7 +83,7 @@ public class SimpleComponentHolder implements IFComponentHolder{
     }
 
     @Override
-    public WXComponent createInstance(WXSDKInstance instance, WXDomObject node, WXVContainer parent) throws IllegalAccessException, InvocationTargetException, InstantiationException {
+    public WXComponent createInstance(WXSDKInstance instance, WXVContainer parent, BasicComponentData basicComponentData) throws IllegalAccessException, InvocationTargetException, InstantiationException {
       if(mConstructor == null){
         loadConstructor();
       }
@@ -91,12 +91,12 @@ public class SimpleComponentHolder implements IFComponentHolder{
       WXComponent component;
 
       if(parameters == 3){
-        component =  mConstructor.newInstance(instance,node,parent);
+        component =  mConstructor.newInstance(instance,parent, basicComponentData);
       }else if(parameters == 4){
-        component =  mConstructor.newInstance(instance,node,parent,false);
+        component =  mConstructor.newInstance(instance,parent,false, basicComponentData);
       }else{
         //compatible deprecated constructor
-        component =  mConstructor.newInstance(instance,node,parent,instance.getInstanceId(),parent.isLazy());
+        component =  mConstructor.newInstance(instance,parent,instance.getInstanceId(),parent.isLazy());
       }
       return component;
     }
@@ -181,8 +181,8 @@ public class SimpleComponentHolder implements IFComponentHolder{
 
 
   @Override
-  public synchronized WXComponent createInstance(WXSDKInstance instance, WXDomObject node, WXVContainer parent) throws IllegalAccessException, InvocationTargetException, InstantiationException {
-    WXComponent component = mCreator.createInstance(instance,node,parent);
+  public synchronized WXComponent createInstance(WXSDKInstance instance, WXVContainer parent, BasicComponentData basicComponentData) throws IllegalAccessException, InvocationTargetException, InstantiationException {
+    WXComponent component = mCreator.createInstance(instance, parent, basicComponentData);
 
     component.bindHolder(this);
     return component;

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/android/sdk/src/main/java/com/taobao/weex/ui/WXComponentRegistry.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/WXComponentRegistry.java b/android/sdk/src/main/java/com/taobao/weex/ui/WXComponentRegistry.java
index 39e3b89..9d8165f 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/WXComponentRegistry.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/WXComponentRegistry.java
@@ -19,6 +19,7 @@
 package com.taobao.weex.ui;
 
 import android.text.TextUtils;
+import android.util.Log;
 
 import com.taobao.weex.WXSDKManager;
 import com.taobao.weex.bridge.WXBridgeManager;

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/android/sdk/src/main/java/com/taobao/weex/ui/WXRenderHandler.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/WXRenderHandler.java b/android/sdk/src/main/java/com/taobao/weex/ui/WXRenderHandler.java
index e133d7b..99cba05 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/WXRenderHandler.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/WXRenderHandler.java
@@ -6,9 +6,9 @@
  * 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
@@ -24,12 +24,18 @@ import android.os.Message;
 
 class WXRenderHandler extends Handler {
 
-  public WXRenderHandler() {
-    super(Looper.getMainLooper());
-  }
+    public WXRenderHandler() {
+        super(Looper.getMainLooper());
+    }
 
-  @Override
-  public void handleMessage(Message msg) {
-    super.handleMessage(msg);
-  }
+    public final boolean post(String instanceId, Runnable r) {
+        Message msg = Message.obtain(this, r);
+        msg.obj = instanceId.hashCode();
+        return sendMessageDelayed(msg, 0);
+    }
+
+    @Override
+    public void handleMessage(Message msg) {
+        super.handleMessage(msg);
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/android/sdk/src/main/java/com/taobao/weex/ui/WXRenderManager.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/WXRenderManager.java b/android/sdk/src/main/java/com/taobao/weex/ui/WXRenderManager.java
index edcc560..04d9395 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/WXRenderManager.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/WXRenderManager.java
@@ -18,20 +18,18 @@
  */
 package com.taobao.weex.ui;
 
-import android.os.SystemClock;
 import android.support.annotation.Nullable;
+import android.support.annotation.RestrictTo;
+import android.support.annotation.RestrictTo.Scope;
 import android.text.TextUtils;
 
 import com.taobao.weex.WXSDKInstance;
+import com.taobao.weex.WXSDKManager;
 import com.taobao.weex.common.WXRuntimeException;
 import com.taobao.weex.common.WXThread;
-import com.taobao.weex.dom.RenderAction;
-import com.taobao.weex.dom.RenderActionContext;
-import com.taobao.weex.dom.WXDomObject;
-import com.taobao.weex.dom.action.AbstractAddElementAction;
-import com.taobao.weex.dom.action.TraceableAction;
-import com.taobao.weex.tracing.Stopwatch;
-import com.taobao.weex.tracing.WXTracing;
+import com.taobao.weex.dom.RenderContext;
+import com.taobao.weex.ui.action.BasicGraphicAction;
+import com.taobao.weex.ui.action.IExecutable;
 import com.taobao.weex.ui.component.WXComponent;
 import com.taobao.weex.utils.WXUtils;
 
@@ -41,33 +39,34 @@ import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
 /**
- * Manager class for render operation, mainly for managing {@link RenderActionContextImpl}.
+ * Manager class for render operation, mainly for managing {@link RenderContextImpl}.
  * This is <strong>not</strong> a thread-safe class
  */
 public class WXRenderManager {
 
-  private ConcurrentHashMap<String, RenderActionContextImpl> mRegistries;
+  private ConcurrentHashMap<String, RenderContextImpl> mRenderContext;
   private WXRenderHandler mWXRenderHandler;
 
   public WXRenderManager() {
-    mRegistries = new ConcurrentHashMap<>();
+    mRenderContext = new ConcurrentHashMap<>();
     mWXRenderHandler = new WXRenderHandler();
   }
 
-  public RenderActionContext getRenderContext(String instanceId) {
-    return mRegistries.get(instanceId);
+  public RenderContext getRenderContext(String instanceId) {
+    return mRenderContext.get(instanceId);
   }
 
-  public @Nullable WXComponent getWXComponent(String instanceId, String ref) {
-    if(instanceId == null || TextUtils.isEmpty(ref)){
+  public @Nullable
+  WXComponent getWXComponent(String instanceId, String ref) {
+    if (instanceId == null || TextUtils.isEmpty(ref)) {
       return null;
     }
-    RenderActionContext stmt = getRenderContext(instanceId);
-    return stmt == null?null:stmt.getComponent(ref);
+    RenderContext stmt = getRenderContext(instanceId);
+    return stmt == null ? null : stmt.getComponent(ref);
   }
 
   public WXSDKInstance getWXSDKInstance(String instanceId) {
-    RenderActionContextImpl statement = mRegistries.get(instanceId);
+    RenderContextImpl statement = mRenderContext.get(instanceId);
     if (statement == null) {
       return null;
     }
@@ -78,95 +77,52 @@ public class WXRenderManager {
     mWXRenderHandler.postDelayed(WXThread.secure(runnable), delayMillis);
   }
 
+  @RestrictTo(Scope.LIBRARY)
+  public void postOnUiThread(Runnable runnable){
+    mWXRenderHandler.post(WXThread.secure(runnable));
+  }
+
+  @RestrictTo(Scope.LIBRARY)
+  public void removeTask(Runnable runnable){
+    mWXRenderHandler.removeCallbacks(runnable);
+  }
+
   /**
    * Remove renderStatement, can only be invoked in UI thread.
+   *
    * @param instanceId {@link WXSDKInstance#mInstanceId}
    */
   public void removeRenderStatement(String instanceId) {
     if (!WXUtils.isUiThread()) {
       throw new WXRuntimeException("[WXRenderManager] removeRenderStatement can only be called in main thread");
     }
-    RenderActionContextImpl statement = mRegistries.remove(instanceId);
+    RenderContextImpl statement = mRenderContext.remove(instanceId);
+
     if (statement != null) {
       statement.destroy();
     }
+    final Object token = instanceId == null ? null : instanceId.hashCode();
+    mWXRenderHandler.removeCallbacksAndMessages(token);
   }
 
-  //TODO Use runnable temporarily
-  public void runOnThread(final String instanceId, final IWXRenderTask task) {
-    mWXRenderHandler.post(WXThread.secure(new Runnable() {
-
-      @Override
-      public void run() {
-        if (mRegistries.get(instanceId) == null) {
-          return;
-        }
-        task.execute();
-      }
-    }));
-  }
-
-  public void runOnThread(final String instanceId, final RenderAction action) {
-    final long start = SystemClock.uptimeMillis();
-    mWXRenderHandler.post(WXThread.secure(new Runnable() {
-      @Override
-      public void run() {
-        if (mRegistries.get(instanceId) == null) {
-          return;
-        }
-        if (WXTracing.isAvailable() && action instanceof TraceableAction) {
-          ((TraceableAction) action).mUIQueueTime = SystemClock.uptimeMillis() - start;
-        }
-
-        long start = System.currentTimeMillis();
-        long uiNanos = System.nanoTime();
-        action.executeRender(getRenderContext(instanceId));
-
-        if (WXTracing.isAvailable()) {
-          uiNanos = System.nanoTime() - uiNanos;
-          if (action instanceof TraceableAction) {
-            if (!(action instanceof AbstractAddElementAction)) {
-              WXTracing.TraceEvent uiExecuteEvent = WXTracing.newEvent("UIExecute", instanceId, ((TraceableAction) action).mTracingEventId);
-              uiExecuteEvent.duration = Stopwatch.nanosToMillis(uiNanos);
-              uiExecuteEvent.ts = start;
-              uiExecuteEvent.submit();
-            }
-            ((TraceableAction) action).onFinishUIExecute();
-          }
-        }
-      }
-    }));
-  }
-
-  public void registerInstance(WXSDKInstance instance) {
-    mRegistries.put(instance.getInstanceId(), new RenderActionContextImpl(instance));
-  }
-
-  public void setLayout(String instanceId, String ref, WXDomObject domObject) {
-    RenderActionContextImpl statement = mRegistries.get(instanceId);
-    if (statement == null) {
+  public void postGraphicAction(final String instanceId, final BasicGraphicAction action) {
+    final RenderContextImpl renderContext = mRenderContext.get(instanceId);
+    if (renderContext == null) {
       return;
     }
-    statement.setLayout(ref, domObject);
+    mWXRenderHandler.post(instanceId, action);
   }
 
-  /**
-   * Set extra info, other than attribute and style
-   */
-  public void setExtra(String instanceId, String ref, Object extra) {
-    RenderActionContextImpl statement = mRegistries.get(instanceId);
-    if (statement == null) {
-      return;
-    }
-    statement.setExtra(ref, extra);
+  public void registerInstance(WXSDKInstance instance) {
+    mRenderContext.put(instance.getInstanceId(), new RenderContextImpl(instance));
   }
 
   public List<WXSDKInstance> getAllInstances() {
     ArrayList<WXSDKInstance> instances = null;
-    if (mRegistries != null && !mRegistries.isEmpty()) {
+    if (mRenderContext != null && !mRenderContext.isEmpty()) {
       instances = new ArrayList<WXSDKInstance>();
-      for (Map.Entry<String, RenderActionContextImpl> entry : mRegistries.entrySet()) {
-        RenderActionContextImpl renderStatement = entry.getValue();
+      for (Map.Entry<String, RenderContextImpl> entry : mRenderContext.entrySet()) {
+        RenderContextImpl renderStatement = entry.getValue();
         if (renderStatement != null) {
           instances.add(renderStatement.getWXSDKInstance());
         }
@@ -176,10 +132,18 @@ public class WXRenderManager {
   }
 
   public void registerComponent(String instanceId, String ref, WXComponent comp) {
-    RenderActionContextImpl statement = mRegistries.get(instanceId);
+    RenderContextImpl statement = mRenderContext.get(instanceId);
     if (statement != null) {
-      statement.registerComponent(ref,comp);
+      statement.registerComponent(ref, comp);
     }
   }
 
+  public WXComponent unregisterComponent(String instanceId, String ref) {
+    RenderContextImpl statement = mRenderContext.get(instanceId);
+    if (statement != null) {
+      return statement.unregisterComponent(ref);
+    } else {
+      return null;
+    }
+  }
 }