Repository: incubator-weex
Updated Branches:
  refs/heads/master 0d2681fcd -> b049f80ee


http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b049f80e/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/WXRecyclerTemplateList.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/WXRecyclerTemplateList.java
 
b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/WXRecyclerTemplateList.java
index 83a4246..3375500 100644
--- 
a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/WXRecyclerTemplateList.java
+++ 
b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/WXRecyclerTemplateList.java
@@ -42,7 +42,6 @@ import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.taobao.weex.WXEnvironment;
 import com.taobao.weex.WXSDKInstance;
-import com.taobao.weex.WXSDKManager;
 import com.taobao.weex.annotation.Component;
 import com.taobao.weex.annotation.JSMethod;
 import com.taobao.weex.common.Constants;
@@ -55,7 +54,6 @@ import com.taobao.weex.dom.WXEvent;
 import com.taobao.weex.el.parse.ArrayStack;
 import com.taobao.weex.ui.action.BasicComponentData;
 import com.taobao.weex.ui.component.AppearanceHelper;
-import com.taobao.weex.ui.component.ComponentUtils;
 import com.taobao.weex.ui.component.Scrollable;
 import com.taobao.weex.ui.component.WXBaseRefresh;
 import com.taobao.weex.ui.component.WXComponent;
@@ -99,7 +97,7 @@ public class WXRecyclerTemplateList extends 
WXVContainer<BounceRecyclerView> imp
     /**
      * trace log for template list
      * */
-    public static final boolean ENABLE_TRACE_LOG = false;
+    public static final boolean ENABLE_TRACE_LOG = true;
 
     public static final String TAG = "WXRecyclerTemplateList";
 
@@ -137,14 +135,12 @@ public class WXRecyclerTemplateList extends 
WXVContainer<BounceRecyclerView> imp
 
 
     private CellDataManager cellDataManager;
-
     private String listDataKey = Constants.Name.Recycler.LIST_DATA;
     private String listDataItemKey = null;
     private String listDataIndexKey = null;
     private ArrayMap<String, Integer> mTemplateViewTypes;
 
 
-
     private Map<String, WXCell> mTemplateSources;
     private String  listDataTemplateKey = 
Constants.Name.Recycler.SLOT_TEMPLATE_CASE;
     private Runnable listUpdateRunnable;
@@ -164,7 +160,6 @@ public class WXRecyclerTemplateList extends 
WXVContainer<BounceRecyclerView> imp
     private ScrollStartEndHelper mScrollStartEndHelper;
 
 
-
     /**
      * sticky helper
      * */
@@ -186,22 +181,27 @@ public class WXRecyclerTemplateList extends 
WXVContainer<BounceRecyclerView> imp
 
     private CellRenderContext cellRenderContext = new CellRenderContext();
 
+    private Runnable mAppearChangeRunnable = null;
+    private static final long APPEAR_CHANGE_RUNNABLE_DELAY = 50;
+
+    /**
+     * has append tree done
+     * */
+    private boolean hasAppendTreeDone = false;
+
+    /**
+     * has layout done
+     * */
+    private boolean hasLayoutDone = false;
+
     public WXRecyclerTemplateList(WXSDKInstance instance, WXVContainer parent, 
BasicComponentData basicComponentData) {
         super(instance, parent, basicComponentData);
-        initRecyclerTemplateList(instance,
-                // TODO
-//                , node
-                parent);
+        initRecyclerTemplateList(instance, basicComponentData, parent);
     }
 
-    private void initRecyclerTemplateList(WXSDKInstance instance,
-                                          // TODO
-//                                          WXDomObject node,
+    private void initRecyclerTemplateList(WXSDKInstance instance, 
BasicComponentData basicComponentData,
                                           WXVContainer parent){
-        // TODO
-//        mDomObject = (WXRecyclerDomObject) node;
-//        mDomObject.preCalculateCellWidth();
-//        mLayoutType = mDomObject.getLayoutType();
+
         updateRecyclerAttr();
 
         mTemplateViewTypes = new ArrayMap<>();
@@ -209,18 +209,12 @@ public class WXRecyclerTemplateList extends 
WXVContainer<BounceRecyclerView> imp
         mTemplateSources = new HashMap<>();
         mTemplatesCache = new ConcurrentHashMap<>();
         mStickyHelper = new TemplateStickyHelper(this);
-        // TODO
-//        orientation = mDomObject.getOrientation();
+        orientation =  basicComponentData.getAttrs().getOrientation();
         listDataTemplateKey = 
WXUtils.getString(getAttrs().get(Constants.Name.Recycler.LIST_DATA_TEMPLATE_SWITCH_KEY),
 Constants.Name.Recycler.SLOT_TEMPLATE_CASE);
         listDataItemKey = 
WXUtils.getString(getAttrs().get(Constants.Name.Recycler.LIST_DATA_ITEM), 
listDataItemKey);
         listDataIndexKey = 
WXUtils.getString(getAttrs().get(Constants.Name.Recycler.LIST_DATA_ITEM_INDEX), 
listDataIndexKey);
         cellDataManager = new CellDataManager(this);
-        if(getAttrs().get(Constants.Name.Recycler.LIST_DATA) instanceof  
JSONArray) {
-            JSONArray array = (JSONArray) 
getAttrs().get(Constants.Name.Recycler.LIST_DATA);
-            if(array.size() > 0) {
-                cellDataManager.listData = array;
-            }
-        }
+        cellDataManager.listData = 
parseListDataToJSONArray(getAttrs().get(Constants.Name.Recycler.LIST_DATA));
         /**
          * we have separate cell with list, post add cell in dom thread ensure
          * list has layout and can archive better user experience and better 
load time,
@@ -413,7 +407,7 @@ public class WXRecyclerTemplateList extends 
WXVContainer<BounceRecyclerView> imp
         if(template == null){
             return;
         }
-        if(cellDataManager.listData == null || mStickyHelper == null){
+        if(mStickyHelper == null){
             return;
         }
         if(!mStickyHelper.getStickyTypes().contains(template.getRef())){
@@ -426,7 +420,6 @@ public class WXRecyclerTemplateList extends 
WXVContainer<BounceRecyclerView> imp
     public void unbindStickStyle(WXComponent component) {
         WXComponent template = findParentType(component, WXCell.class);
         if(template == null
-                || cellDataManager.listData == null
                 || mStickyHelper == null){
             return;
         }
@@ -483,11 +476,39 @@ public class WXRecyclerTemplateList extends 
WXVContainer<BounceRecyclerView> imp
     @Override
     public void bindAppearEvent(WXComponent component) {
         setAppearanceWatch(component, AppearanceHelper.APPEAR, true);
+        if(mAppearChangeRunnable == null){
+            mAppearChangeRunnable =  new Runnable() {
+                @Override
+                public void run() {
+                    if(mAppearChangeRunnable != null) {
+                        notifyAppearStateChange(0, 0, 0, 0);
+                    }
+                }
+            };
+        }
+        if (getHostView() != null) {
+            getHostView().removeCallbacks(mAppearChangeRunnable);
+            getHostView().postDelayed(mAppearChangeRunnable, 
APPEAR_CHANGE_RUNNABLE_DELAY);
+        }
     }
 
     @Override
     public void bindDisappearEvent(WXComponent component) {
         setAppearanceWatch(component, AppearanceHelper.DISAPPEAR, true);
+        if(mAppearChangeRunnable == null){
+            mAppearChangeRunnable =  new Runnable() {
+                @Override
+                public void run() {
+                    if(mAppearChangeRunnable != null) {
+                        notifyAppearStateChange(0, 0, 0, 0);
+                    }
+                }
+            };
+        }
+        if (getHostView() != null) {
+            getHostView().removeCallbacks(mAppearChangeRunnable);
+            getHostView().postDelayed(mAppearChangeRunnable, 
APPEAR_CHANGE_RUNNABLE_DELAY);
+        }
     }
 
     @Override
@@ -652,18 +673,50 @@ public class WXRecyclerTemplateList extends 
WXVContainer<BounceRecyclerView> imp
 //                        domObject.setRecyclerDomObject((WXRecyclerDomObject) 
getDomObject());
 //                    }
                     mTemplateSources.put(key, (WXCell) child);
-                    renderTemplateCellWithData((WXCell)child);
                     if(mTemplateViewTypes.get(key) == null){
                         mTemplateViewTypes.put(key, mTemplateViewTypes.size());
                     }
                 }
             }
-            notifyUpdateList();
+
+            ((WXCell) child).setCellAppendTreeListener(new 
WXCell.CellAppendTreeListener() {
+                @Override
+                public void onAppendTreeDone() {
+                    checkAppendDone(false);
+                }
+            });
         }
     }
 
 
+    /**
+     * check all the cell has append tree done, then show list
+     * */
+    private void  checkAppendDone(boolean listDone){
+        if(mTemplateSources.size() == 0){
+            return;
+        }
+        Set<Map.Entry<String,WXCell>> cells = mTemplateSources.entrySet();
+        for(Map.Entry<String,WXCell> entry : cells){
+            if(!entry.getValue().isAppendTreeDone()){
+                return;
+            }
+        }
+        hasAppendTreeDone = true;
+        if(hasLayoutDone) {
+            notifyUpdateList();
+        }
+    }
 
+    @Override
+    protected void setHostLayoutParams(BounceRecyclerView host, int width, int 
height, int left, int right, int top, int bottom) {
+        super.setHostLayoutParams(host, width, height, left, right, top, 
bottom);
+        if(!hasLayoutDone){
+            hasLayoutDone = true;
+            hasAppendTreeDone = true;
+            notifyUpdateList();
+        }
+    }
 
 
     /**
@@ -764,6 +817,7 @@ public class WXRecyclerTemplateList extends 
WXVContainer<BounceRecyclerView> imp
 
 
     private void updateRecyclerAttr(){
+        mLayoutType = getAttrs().getLayoutType();
         mColumnCount = getAttrs().getColumnCount();
         mColumnGap = getAttrs().getColumnGap();
         mColumnWidth = getAttrs().getColumnWidth();
@@ -832,6 +886,7 @@ public class WXRecyclerTemplateList extends 
WXVContainer<BounceRecyclerView> imp
 
     @JSMethod
     public void setListData(Object param){
+        param = parseListDataToJSONArray(param);
         boolean update = cellDataManager.listData != param;
         if(param instanceof  JSONArray){
             if(update){
@@ -1118,7 +1173,12 @@ public class WXRecyclerTemplateList extends 
WXVContainer<BounceRecyclerView> imp
 
     @Override
     public void destroy() {
+
         if(getHostView() != null){
+            if(mAppearChangeRunnable != null) {
+                getHostView().removeCallbacks(mAppearChangeRunnable);
+                mAppearChangeRunnable = null;
+            }
             getHostView().removeCallbacks(listUpdateRunnable);
             if(getHostView().getInnerView() != null){
                 getHostView().getInnerView().setAdapter(null);
@@ -1163,9 +1223,10 @@ public class WXRecyclerTemplateList extends 
WXVContainer<BounceRecyclerView> imp
         templateViewHolder.setHolderPosition(position);
         Object data = cellDataManager.listData.get(position);
         CellRenderState cellRenderState = 
cellDataManager.getRenderState(position);
-        if(component.getRenderData() == data && (cellRenderState == null || 
!cellRenderState.isDirty())){
+        if((component.getRenderData() == data && (cellRenderState == null || 
!cellRenderState.isDirty()))){
             if(WXEnvironment.isOpenDebugLog() && ENABLE_TRACE_LOG){
-                WXLogUtils.d(TAG,  position + " position "+ 
getTemplateKey(position) + " onBindViewHolder none data update ");
+                WXLogUtils.d(TAG,  position + " position "+ 
getTemplateKey(position) + " onBindViewHolder none data update "
+                        + " component " + component.hashCode());
             }
             return;  //none update just return
         }else{
@@ -1174,7 +1235,8 @@ public class WXRecyclerTemplateList extends 
WXVContainer<BounceRecyclerView> imp
             component.setRenderData(data);
             Layouts.doLayoutAsync(templateViewHolder, true);
             if(WXEnvironment.isOpenDebugLog() && ENABLE_TRACE_LOG){
-                WXLogUtils.d(TAG,  position + " position "+ 
getTemplateKey(position) + " onBindViewHolder used " + 
(System.currentTimeMillis() - start));
+                WXLogUtils.d(TAG,  position + " position "+ 
getTemplateKey(position) + " onBindViewHolder used " + 
(System.currentTimeMillis() - start)
+                  + " component " + component.hashCode());
             }
         }
     }
@@ -1186,7 +1248,7 @@ public class WXRecyclerTemplateList extends 
WXVContainer<BounceRecyclerView> imp
         if(source == null){
             FrameLayout view = new FrameLayout(getContext());
             view.setLayoutParams(new FrameLayout.LayoutParams(0, 0));
-            return new TemplateViewHolder(view, viewType);
+            return new TemplateViewHolder(this, view, viewType);
         }
         WXCell component =  getCellTemplateFromCache(template);
         boolean cacheHit = true;
@@ -1208,64 +1270,22 @@ public class WXRecyclerTemplateList extends 
WXVContainer<BounceRecyclerView> imp
                 WXLogUtils.d(TAG, template + " onCreateViewHolder copy used " 
+ (System.currentTimeMillis() - start));
             }
         }
-        if(component.isLazy()) {
+        if(component.isLazy() || component.getHostView() == null) {
             doCreateCellViewBindData(component, template, false);
             if(WXEnvironment.isOpenDebugLog() && ENABLE_TRACE_LOG) {
                 WXLogUtils.d(TAG, template + " onCreateViewHolder  cache hit " 
+ cacheHit   + " view not idle init");
             }
         }else{
             if(WXEnvironment.isOpenDebugLog() && ENABLE_TRACE_LOG) {
-                WXLogUtils.d(TAG, template + " onCreateViewHolder  cache hit " 
+ cacheHit + " view idle init");
+                WXLogUtils.d(TAG, template + " onCreateViewHolder  cache hit " 
+ cacheHit + " view idle init " + component.hashCode()
+                 + "  " + source.hashCode());
             }
         }
-        TemplateViewHolder templateViewHolder = new 
TemplateViewHolder(component, viewType);
+        TemplateViewHolder templateViewHolder = new TemplateViewHolder(this, 
component, viewType);
         return  templateViewHolder;
     }
 
 
-    /**
-     * copy cell component from source, init render data, and return source
-     * if none data, return null
-     * */
-    public WXComponent copyComponentFromSourceCell(WXCell cell){
-        renderTemplateCellWithData(cell);
-        WXCell component = (WXCell) Statements.copyComponentTree(cell);
-        // TODO
-//        if(component.getDomObject() instanceof  WXCellDomObject
-//                && getDomObject() instanceof  WXRecyclerDomObject){
-//            WXCellDomObject domObject = (WXCellDomObject) 
component.getDomObject();
-//            domObject.setRecyclerDomObject((WXRecyclerDomObject) 
getDomObject());
-//        }
-        component.setRenderData(cell.getRenderData());
-        return component;
-    }
-
-    /**
-     *  render  init with  cell with one data,
-     *  if template has already render with data, done nothing
-     *  @param  cell
-     * */
-    private synchronized void renderTemplateCellWithData(WXCell cell){
-        if(cell.getRenderData() == null){
-            if(cellDataManager.listData != null && 
cellDataManager.listData.size() > 0){
-                synchronized (this){
-                    if(cell.getRenderData() == null){
-                        for(int i = 0; i< cellDataManager.listData.size(); 
i++){
-                            if(cell == getSourceTemplate(i)){
-                                Object data = cellDataManager.listData.get(i);
-                                doRenderTemplate(cell, i);
-                                Layouts.doSafeLayout(cell
-//                                        , new CSSLayoutContext()
-                                );
-                                cell.setRenderData(data);
-                                break;
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
 
     /**
      * @param position
@@ -1391,6 +1411,12 @@ public class WXRecyclerTemplateList extends 
WXVContainer<BounceRecyclerView> imp
 
     @Override
     public int getItemCount() {
+        if(!hasLayoutDone){
+            return 0;
+        }
+        if(!hasAppendTreeDone){
+            return 0;
+        }
         if(cellDataManager.listData == null){
             return  0;
         }
@@ -1474,6 +1500,10 @@ public class WXRecyclerTemplateList extends 
WXVContainer<BounceRecyclerView> imp
                 || mAppearHelpers.size() <= 0){
             return;
         }
+        if(mAppearChangeRunnable != null) {
+            getHostView().removeCallbacks(mAppearChangeRunnable);
+            mAppearChangeRunnable = null;
+        }
         String direction = directionY > 0 ? Constants.Value.DIRECTION_UP :
                 directionY < 0 ? Constants.Value.DIRECTION_DOWN : null;
         if (getOrientation() == Constants.Orientation.HORIZONTAL && directionX 
!= 0) {
@@ -1660,7 +1690,7 @@ public class WXRecyclerTemplateList extends 
WXVContainer<BounceRecyclerView> imp
      * find certain class type parent
      * */
     public WXComponent findParentType(WXComponent component, Class type){
-        if(component.getClass() == type){
+        if(type.isAssignableFrom(component.getClass())){
             return component;
         }
         if(component.getParent() != null) {
@@ -1744,12 +1774,49 @@ public class WXRecyclerTemplateList extends 
WXVContainer<BounceRecyclerView> imp
     }
 
     /**
+     * copy cell component from source, init render data, and return source
+     * if none data, return null
+     * */
+    public WXComponent copyComponentFromSourceCell(WXCell cell){
+        renderTemplateCellWithData(cell);
+        WXCell component = (WXCell) Statements.copyComponentTree(cell);
+        return component;
+    }
+
+    /**
+     *  render  init with  cell with one data,
+     *  if template has already render with data, done nothing
+     *  @param  cell
+     * */
+    private synchronized void renderTemplateCellWithData(WXCell cell){
+        if(cell.getRenderData() == null){
+            if(cellDataManager.listData != null && 
cellDataManager.listData.size() > 0){
+                synchronized (this){
+                    if(cell.getRenderData() == null){
+                        Statements.parseStatementsToken(cell);
+                        for(int i = 0; i< cellDataManager.listData.size(); 
i++){
+                            if(cell == getSourceTemplate(i)){
+                                Object data = cellDataManager.listData.get(i);
+                                doRenderTemplate(cell, i);
+                                Layouts.doLayoutSync(cell, getLayoutWidth(), 
getLayoutHeight());
+                                cell.setRenderData(data);
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+
+    /**
      * create view for lazy cell and bind data
      * */
     public static void doCreateCellViewBindData(WXCell component, String 
template, boolean inPreload){
-        if(component.isLazy()){
+        if(component.isLazy() || component.getHostView() == null){
             long start = System.currentTimeMillis();
-            ComponentUtils.initLazyComponent(component, null);
+            Statements.initLazyComponent(component, null);
             if(WXEnvironment.isOpenDebugLog() && ENABLE_TRACE_LOG) {
                 WXLogUtils.d(TAG, " doCreateCellViewBindData " + template + " 
in preload "+ inPreload + " used " + (System.currentTimeMillis() - start));
             }
@@ -1778,4 +1845,20 @@ public class WXRecyclerTemplateList extends 
WXVContainer<BounceRecyclerView> imp
     public CellDataManager getCellDataManager() {
         return cellDataManager;
     }
+
+
+    private JSONArray parseListDataToJSONArray(Object value){
+        try{
+            if(value instanceof  JSONArray){
+                return (JSONArray) value;
+            }
+            if(value instanceof String){
+                JSONArray array = 
JSONArray.parseArray(getAttrs().get(Constants.Name.Recycler.LIST_DATA).toString());
+                return array;
+            }
+        }catch (Exception e){
+            WXLogUtils.e(TAG, "parseListDataException" + e.getMessage());
+        }
+        return new JSONArray();
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b049f80e/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/jni/NativeRenderObjectUtils.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/jni/NativeRenderObjectUtils.java
 
b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/jni/NativeRenderObjectUtils.java
new file mode 100644
index 0000000..c477413
--- /dev/null
+++ 
b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/jni/NativeRenderObjectUtils.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.ui.component.list.template.jni;
+
+import android.util.Log;
+
+import com.taobao.weex.base.CalledByNative;
+import com.taobao.weex.ui.component.WXComponent;
+
+/**
+ * Created by furture on 2018/5/3.
+ */
+
+public class NativeRenderObjectUtils {
+
+
+    /**
+     * getRenderObject
+     * */
+    public static native long nativeGetRenderObject(String instanceId, String 
ref);
+
+    /**
+     * render object layout
+     * */
+    public static native void nativeUpdateRenderObjectStyle(long ptr, String 
key, String value);
+    public static native void nativeUpdateRenderObjectAttr(long ptr, String 
key, String value);
+
+    /**
+     * copy render object
+     * */
+    public static native long nativeCopyRenderObject(long ptr);
+
+    /**
+     * layout render object
+     * */
+    public static native int nativeLayoutRenderObject(long ptr, float width, 
float height);
+
+    /**
+     * get child length
+     * */
+    public static native void nativeAddChildRenderObject(long parent, long 
child);
+
+    /**
+     * get component, tranverse child and update component
+     * */
+    public static native boolean nativeRenderObjectHasNewLayout(long ptr);
+    public static native int nativeRenderObjectChildCount(long ptr);
+    public static native long nativeRenderObjectGetChild(long ptr, int index);
+    public static native long nativeRenderObjectUpdateComponent(long ptr, 
WXComponent component);
+    public static native void nativeRenderObjectChildWaste(long ptr, boolean 
waster);
+
+
+    /**
+     * component size
+     * */
+    @CalledByNative
+    public static void updateComponentSize(WXComponent component, float top, 
float bottom, float left, float right, float height, float width){
+        component.updateDemission(top, bottom, left, right, height, width);
+        component.applyLayoutOnly();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b049f80e/android/sdk/src/main/java/com/taobao/weex/ui/module/WXDomModule.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/ui/module/WXDomModule.java 
b/android/sdk/src/main/java/com/taobao/weex/ui/module/WXDomModule.java
index 38daf3f..14fa644 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/module/WXDomModule.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/module/WXDomModule.java
@@ -23,10 +23,12 @@ import com.alibaba.fastjson.JSONObject;
 import com.taobao.weex.WXSDKInstance;
 import com.taobao.weex.bridge.WXBridgeManager;
 import com.taobao.weex.common.WXModule;
+import com.taobao.weex.dom.binding.JSONUtils;
 import com.taobao.weex.ui.action.ActionAddRule;
 import com.taobao.weex.ui.action.ActionGetComponentRect;
 import com.taobao.weex.ui.action.ActionInvokeMethod;
 import com.taobao.weex.ui.action.GraphicActionScrollToElement;
+import com.taobao.weex.ui.action.UpdateComponentDataAction;
 import com.taobao.weex.utils.WXLogUtils;
 
 /**
@@ -46,6 +48,8 @@ public final class WXDomModule extends WXModule {
   public static final String WXDOM = "dom";
   public static final String INVOKE_METHOD = "invokeMethod";
 
+  public static final String UPDATE_COMPONENT_DATA = "updateComponentData";
+
   /**
    * Methods expose to js. Every method which will be called in js should add 
to this array.
    */
@@ -108,6 +112,12 @@ public final class WXDomModule extends WXModule {
                   .executeAction();
           break;
         }
+        case UPDATE_COMPONENT_DATA:
+          if(args == null || args.size() < 3){
+            return null;
+          }
+          new UpdateComponentDataAction(mWXSDKInstance.getInstanceId(), 
args.getString(0), JSONUtils.toJSON(args.get(1)), 
args.getString(2)).executeAction();
+          break;
         default:
           WXLogUtils.e("Unknown dom action.");
           break;

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b049f80e/weex_core/Source/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/weex_core/Source/CMakeLists.txt b/weex_core/Source/CMakeLists.txt
index 478680a..ef92a1f 100644
--- a/weex_core/Source/CMakeLists.txt
+++ b/weex_core/Source/CMakeLists.txt
@@ -37,6 +37,7 @@ add_library(weexjsc SHARED
     ./android/bridge/impl/measure_mode_impl_android.cpp
     ./android/bridge/impl/content_box_measurement_impl_android.cpp
     ./android/bridge/impl/jsfunction_impl_android.cpp
+    ./android/bridge/impl/native_render_object_utils_impl_android.cpp
 
     ./android/jsengine/multiprocess/WeexJSConnection.cpp
     ./android/jsengine/multiprocess/WeexProxy.cpp

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b049f80e/weex_core/Source/android/bridge/impl/bridge_impl_android.cpp
----------------------------------------------------------------------
diff --git a/weex_core/Source/android/bridge/impl/bridge_impl_android.cpp 
b/weex_core/Source/android/bridge/impl/bridge_impl_android.cpp
index 9e0dc9b..27a4b92 100644
--- a/weex_core/Source/android/bridge/impl/bridge_impl_android.cpp
+++ b/weex_core/Source/android/bridge/impl/bridge_impl_android.cpp
@@ -472,7 +472,8 @@ namespace WeexCore {
                                           std::set<std::string> *events,
                                           const WXCoreMargin &margins,
                                           const WXCorePadding &paddings,
-                                          const WXCoreBorderWidth &borders) {
+                                          const WXCoreBorderWidth &borders,
+                                          bool willLayout) {
     JNIEnv *env = getJNIEnv();
     jstring jPageId = env->NewStringUTF(pageId);
     jstring jRef = env->NewStringUTF(ref);
@@ -535,7 +536,7 @@ namespace WeexCore {
     if (jCallAddElementMethodId == NULL)
       jCallAddElementMethodId = env->GetMethodID(jBridgeClazz,
                                                            "callAddElement",
-                                                           
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/util/HashMap;Ljava/util/HashMap;Ljava/util/HashSet;[F[F[F)I");
+                                                           
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/util/HashMap;Ljava/util/HashMap;Ljava/util/HashSet;[F[F[FZ)I");
 
     jstring jComponentType = getComponentTypeFromCache(componentType);
     if (jComponentType == nullptr) {
@@ -544,7 +545,7 @@ namespace WeexCore {
 
     int flag = 0;
     flag = env->CallIntMethod(jThis, jCallAddElementMethodId, jPageId, 
jComponentType, jRef, index,
-                              jParentRef, jStyles, jAttributes, jEvents, 
jMargins, jPaddings, jBorders);
+                              jParentRef, jStyles, jAttributes, jEvents, 
jMargins, jPaddings, jBorders, willLayout);
 
     page->CallBridgeTime(getCurrentTime() - startTimeCallBridge);
 

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b049f80e/weex_core/Source/android/bridge/impl/bridge_impl_android.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/android/bridge/impl/bridge_impl_android.h 
b/weex_core/Source/android/bridge/impl/bridge_impl_android.h
index 3f73370..fee8942 100644
--- a/weex_core/Source/android/bridge/impl/bridge_impl_android.h
+++ b/weex_core/Source/android/bridge/impl/bridge_impl_android.h
@@ -101,7 +101,8 @@ namespace WeexCore {
                        std::set<std::string> *events,
                        const WXCoreMargin &margins,
                        const WXCorePadding &paddings,
-                       const WXCoreBorderWidth &borders);
+                       const WXCoreBorderWidth &borders,
+                       bool willLayout= true);
 
     int callRemoveElement(const char* pageId, const char* ref);
 

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b049f80e/weex_core/Source/android/bridge/impl/native_render_object_utils_impl_android.cpp
----------------------------------------------------------------------
diff --git 
a/weex_core/Source/android/bridge/impl/native_render_object_utils_impl_android.cpp
 
b/weex_core/Source/android/bridge/impl/native_render_object_utils_impl_android.cpp
new file mode 100644
index 0000000..6d43347
--- /dev/null
+++ 
b/weex_core/Source/android/bridge/impl/native_render_object_utils_impl_android.cpp
@@ -0,0 +1,209 @@
+/**
+ * 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.
+ */
+//
+// Created by furture on 2018/5/4.
+//
+
+#include "native_render_object_utils_impl_android.h"
+#include <android/base/jni/android_jni.h>
+#include <android/jniprebuild/jniheader/NativeRenderObjectUtils_jni.h>
+#include <core/render/page/render_page.h>
+#include <core/render/manager/render_manager.h>
+#include <android/base/string/string_utils.h>
+#include <core/render/node/factory/render_creator.h>
+#include <core/render/node/render_object.h>
+#include <core/render/node/factory/render_type.h>
+#include <android/log.h>
+#include <core/render/node/render_list.h>
+
+
+using namespace WeexCore;
+
+namespace WeexCore {
+    bool RegisterJNINativeRenderObjectUtils(JNIEnv *env){
+        RegisterNativesImpl(env);
+        return true;
+    }
+}
+
+
+
+static jlong GetRenderObject(JNIEnv* env, jclass jcaller,
+                             jstring instanceId,
+                             jstring ref){
+    RenderPage *page = 
RenderManager::GetInstance()->GetPage(jString2StrFast(env, instanceId));
+    if (page == nullptr){
+        return 0;
+    }
+
+    RenderObject *render = page->GetRenderObject(jString2StrFast(env, ref));
+    if (render == nullptr){
+        return 0;
+    }
+    return convert_render_object_to_long(render);
+}
+
+
+
+static void UpdateRenderObjectStyle(JNIEnv* env, jclass jcaller,
+                                    jlong ptr,
+                                    jstring key,
+                                    jstring value){
+
+    RenderObject *render  = convert_long_to_render_object(ptr);
+    render->UpdateStyle(jString2StrFast(env, key), jString2StrFast(env, 
value));
+}
+
+static void UpdateRenderObjectAttr(JNIEnv* env, jclass jcaller,
+                                   jlong ptr,
+                                   jstring key,
+                                   jstring value){
+    RenderObject *render  = convert_long_to_render_object(ptr);
+    render->UpdateAttr(jString2StrFast(env, key), jString2StrFast(env, value));
+    render->markDirty(true);
+}
+
+static jlong CopyRenderObject(JNIEnv* env, jclass jcaller, jlong ptr){
+    RenderObject *render = convert_long_to_render_object(ptr);
+    RenderObject *copy = 
(RenderObject*)RenderCreator::GetInstance()->CreateRender(render->Type(), 
render->Ref());
+    copy->copyFrom(render);
+    if(render->Type() == WeexCore::kRenderCellSlot || render->Type() == 
WeexCore::kRenderCell){
+        RenderList* renderList = static_cast<RenderList*>(render->getParent());
+        if(renderList != nullptr){
+            renderList->addCellSlotCopyTrack(copy);
+        }else{
+            __android_log_print(ANDROID_LOG_ERROR, " LayoutRenderObject","copy 
error parent null");
+        }
+    }
+    return  convert_render_object_to_long(copy);
+}
+
+static  void showRenderObjectLayout(RenderObject *renderObject, int level){
+   LOGE("RenderObject", "layout %s %d %p %f %f %f %f ",  
renderObject->Type().c_str(),
+                        renderObject->getStypePositionType(),
+                        renderObject, renderObject->getLayoutHeight(), 
renderObject->getLayoutWidth(),
+    renderObject->getLayoutPositionLeft(), 
renderObject->getLayoutPositionRight());
+    for(auto it = renderObject->ChildListIterBegin(); it != 
renderObject->ChildListIterEnd(); it++){
+        RenderObject* child = static_cast<RenderObject*>(*it);
+        showRenderObjectLayout(child, level + 1);
+    }
+}
+
+static jint LayoutRenderObject(JNIEnv* env, jclass jcaller,
+                               jlong ptr,
+                               jfloat width,
+                               jfloat height){
+    if(width <= 0){
+         width = WXCoreEnvironment::getInstance()->DeviceWidth();
+    }
+
+    std::pair<float,float> renderPageSize;
+    renderPageSize.first= width;
+
+    if(height > 0){
+        renderPageSize.second = height;
+    }else{
+        renderPageSize.second = NAN;
+    }
+
+    RenderObject *render = convert_long_to_render_object(ptr);
+    if(render->Type() == WeexCore::kRenderCell ||  render->Type() == 
WeexCore::kRenderCellSlot){
+        RenderList* renderList = static_cast<RenderList*>(render->getParent());
+        if(renderList != nullptr){
+            if(renderList->getColumnCount() > 1  && 
renderList->getColumnWidth() > 0){
+                renderPageSize.first = renderList->getColumnWidth();
+            }
+        }
+    }
+
+    if(render->getStyleWidth() != renderPageSize.first){
+        render->setStyleWidth(renderPageSize.first, true);
+        render->setStyleWidthLevel(CSS_STYLE);
+    }
+
+    render->LayoutBefore();
+    render->calculateLayout(renderPageSize);
+    render->LayoutAfter();
+
+    return (jint)render->getLayoutHeight();
+}
+
+
+
+
+static jboolean RenderObjectHasNewLayout(JNIEnv* env, jclass jcaller,
+                                     jlong ptr){
+    RenderObject* renderObject = convert_long_to_render_object(ptr);
+    return renderObject->hasNewLayout();
+}
+
+static jint RenderObjectChildCount(JNIEnv* env, jclass jcaller,
+                                   jlong ptr){
+    RenderObject* renderObject = convert_long_to_render_object(ptr);
+    return renderObject->getChildCount();
+}
+
+static jlong RenderObjectGetChild(JNIEnv* env, jclass jcaller,
+                                  jlong ptr,
+                                  jint index){
+    RenderObject* parent = convert_long_to_render_object(ptr);
+    RenderObject* child = (RenderObject *) parent->getChildAt(index);
+    return convert_render_object_to_long(child);
+}
+
+static jlong RenderObjectUpdateComponent(JNIEnv* env, jclass jcaller,
+                                         jlong ptr,
+                                         jobject component){
+    RenderObject* renderObject = convert_long_to_render_object(ptr);
+    float mTop = renderObject->getLayoutPositionTop();
+    float mBottom = renderObject->getLayoutPositionBottom();
+    float mRight = renderObject->getLayoutPositionRight();
+    float mLeft = renderObject->getLayoutPositionLeft();
+    float mHeight = renderObject->getLayoutHeight();
+    float mWidth = renderObject->getLayoutWidth();
+    Java_NativeRenderObjectUtils_updateComponentSize(env, component,mTop, 
mBottom,mLeft, mRight, mHeight, mWidth);
+    renderObject->setHasNewLayout(false);
+}
+
+
+static void RenderObjectChildWaste(JNIEnv* env, jclass jcaller,
+                                   jlong ptr,
+                                   jboolean waster){
+    RenderObject* renderObject = convert_long_to_render_object(ptr);
+    if(waster){
+        if(renderObject->getStypePositionType() != WXCorePositionType::kFixed){
+            renderObject->setStylePositionType(WXCorePositionType::kFixed);
+        }
+    }else{
+        if(renderObject->getStypePositionType() != 
WXCorePositionType::kRelative){
+            renderObject->setStylePositionType(WXCorePositionType::kRelative);
+        }
+    }
+}
+
+
+
+
+static void AddChildRenderObject(JNIEnv* env, jclass jcaller,
+                                 jlong parent,
+                                 jlong child){
+    RenderObject *renderParent = convert_long_to_render_object(parent);
+    RenderObject *renderChild = convert_long_to_render_object(child);
+    renderParent->AddRenderObject(-1, renderChild);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b049f80e/weex_core/Source/android/bridge/impl/native_render_object_utils_impl_android.h
----------------------------------------------------------------------
diff --git 
a/weex_core/Source/android/bridge/impl/native_render_object_utils_impl_android.h
 
b/weex_core/Source/android/bridge/impl/native_render_object_utils_impl_android.h
new file mode 100644
index 0000000..4887659
--- /dev/null
+++ 
b/weex_core/Source/android/bridge/impl/native_render_object_utils_impl_android.h
@@ -0,0 +1,34 @@
+/**
+ * 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.
+ */
+//
+// Created by furture on 2018/5/4.
+//
+
+#ifndef WEEX_PROJECT_NATIVE_RENDER_OBJECT_UTILS_IMPL_ANDROID_H
+#define WEEX_PROJECT_NATIVE_RENDER_OBJECT_UTILS_IMPL_ANDROID_H
+
+
+#include <jni.h>
+
+namespace WeexCore{
+    bool RegisterJNINativeRenderObjectUtils(JNIEnv *env);
+}
+
+
+#endif //WEEX_PROJECT_NATIVE_RENDER_OBJECT_UTILS_IMPL_ANDROID_H

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b049f80e/weex_core/Source/android/bridge/impl/weexcore_impl_android.cpp
----------------------------------------------------------------------
diff --git a/weex_core/Source/android/bridge/impl/weexcore_impl_android.cpp 
b/weex_core/Source/android/bridge/impl/weexcore_impl_android.cpp
index 133b2ed..d5dcd10 100644
--- a/weex_core/Source/android/bridge/impl/weexcore_impl_android.cpp
+++ b/weex_core/Source/android/bridge/impl/weexcore_impl_android.cpp
@@ -115,6 +115,15 @@ static void BindMeasurementToWXCore(JNIEnv *env, jobject 
jcaller, jstring instan
   render->BindMeasureFuncImplAndroid(contentBoxMeasurement);
 }
 
+static void BindMeasurementToRenderObject(JNIEnv* env, jobject jcaller,
+                                          jlong ptr,
+                                          jobject contentBoxMeasurement){
+  RenderObject *render =  convert_long_to_render_object(ptr);
+  if(render){
+    render->BindMeasureFuncImplAndroid(contentBoxMeasurement);
+  }
+}
+
 static void OnInstanceClose(JNIEnv *env, jobject jcaller, jstring instanceId) {
   RenderManager::GetInstance()->ClosePage(jString2StrFast(env, instanceId));
 }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b049f80e/weex_core/Source/android/jniprebuild/jni_files
----------------------------------------------------------------------
diff --git a/weex_core/Source/android/jniprebuild/jni_files 
b/weex_core/Source/android/jniprebuild/jni_files
index 5aadd44..0fc5493 100644
--- a/weex_core/Source/android/jniprebuild/jni_files
+++ b/weex_core/Source/android/jniprebuild/jni_files
@@ -1,3 +1,4 @@
+com/taobao/weex/ui/component/list/template/jni/NativeRenderObjectUtils.java
 com/taobao/weex/base/SystemMessageHandler.java
 com/taobao/weex/bridge/WXBridge.java
 com/taobao/weex/layout/MeasureMode.java

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b049f80e/weex_core/Source/android/jniprebuild/jni_load.cc
----------------------------------------------------------------------
diff --git a/weex_core/Source/android/jniprebuild/jni_load.cc 
b/weex_core/Source/android/jniprebuild/jni_load.cc
index 77ffb7f..365ebbd 100644
--- a/weex_core/Source/android/jniprebuild/jni_load.cc
+++ b/weex_core/Source/android/jniprebuild/jni_load.cc
@@ -4,6 +4,7 @@
 #include <android/bridge/impl/measure_mode_impl_android.h>
 #include <android/bridge/impl/content_box_measurement_impl_android.h>
 #include <android/bridge/impl/jsfunction_impl_android.h>
+#include <android/bridge/impl/native_render_object_utils_impl_android.h>
 
 jint JNI_OnLoad (JavaVM *vm, void *reserved)
 {
@@ -18,6 +19,7 @@ jint JNI_OnLoad (JavaVM *vm, void *reserved)
     WeexCore::RegisterJNIMeasureMode(env);
     WeexCore::RegisterJNIContentBoxMeasurement(env);
     WeexCore::RegisterWXJsFunction(env);
+    WeexCore::RegisterJNINativeRenderObjectUtils(env);
     return WeexCore::OnLoad(vm, reserved);
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b049f80e/weex_core/Source/android/jniprebuild/jniheader/ContentBoxMeasurement_jni.h
----------------------------------------------------------------------
diff --git 
a/weex_core/Source/android/jniprebuild/jniheader/ContentBoxMeasurement_jni.h 
b/weex_core/Source/android/jniprebuild/jniheader/ContentBoxMeasurement_jni.h
index 38bc77b..05c62f7 100644
--- a/weex_core/Source/android/jniprebuild/jniheader/ContentBoxMeasurement_jni.h
+++ b/weex_core/Source/android/jniprebuild/jniheader/ContentBoxMeasurement_jni.h
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 // This file is autogenerated by
-//     
weex_core_debug/Source/WeexCore/platform/android/jniprebuild/jni_generator.py
+//    weex-core2/weex_core/Source/android/jniprebuild/jni_generator.py
 // For
 //     com/taobao/weex/layout/ContentBoxMeasurement
 

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b049f80e/weex_core/Source/android/jniprebuild/jniheader/NativeRenderObjectUtils_jni.h
----------------------------------------------------------------------
diff --git 
a/weex_core/Source/android/jniprebuild/jniheader/NativeRenderObjectUtils_jni.h 
b/weex_core/Source/android/jniprebuild/jniheader/NativeRenderObjectUtils_jni.h
new file mode 100644
index 0000000..0a100e2
--- /dev/null
+++ 
b/weex_core/Source/android/jniprebuild/jniheader/NativeRenderObjectUtils_jni.h
@@ -0,0 +1,200 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file is autogenerated by
+//     /Users/furture/weex-
+//    core2/weex_core/Source/android/jniprebuild/jni_generator.py
+// For
+//     com/taobao/weex/ui/component/list/template/jni/NativeRenderObjectUtils
+
+#ifndef 
com_taobao_weex_ui_component_list_template_jni_NativeRenderObjectUtils_JNI
+#define 
com_taobao_weex_ui_component_list_template_jni_NativeRenderObjectUtils_JNI
+
+#include <jni.h>
+
+//#include "base/android/jni_int_wrapper.h"
+
+// Step 1: forward declarations.
+namespace {
+const char kNativeRenderObjectUtilsClassPath[] =
+    "com/taobao/weex/ui/component/list/template/jni/NativeRenderObjectUtils";
+// Leaking this jclass as we cannot use LazyInstance from some threads.
+jclass g_NativeRenderObjectUtils_clazz = NULL;
+#define NativeRenderObjectUtils_clazz(env) g_NativeRenderObjectUtils_clazz
+
+}  // namespace
+
+static jlong GetRenderObject(JNIEnv* env, jclass jcaller,
+    jstring instanceId,
+    jstring ref);
+
+static void UpdateRenderObjectStyle(JNIEnv* env, jclass jcaller,
+    jlong ptr,
+    jstring key,
+    jstring value);
+
+static void UpdateRenderObjectAttr(JNIEnv* env, jclass jcaller,
+    jlong ptr,
+    jstring key,
+    jstring value);
+
+static jlong CopyRenderObject(JNIEnv* env, jclass jcaller,
+    jlong ptr);
+
+static jint LayoutRenderObject(JNIEnv* env, jclass jcaller,
+    jlong ptr,
+    jfloat width,
+    jfloat height);
+
+static void AddChildRenderObject(JNIEnv* env, jclass jcaller,
+    jlong parent,
+    jlong child);
+
+static jboolean RenderObjectHasNewLayout(JNIEnv* env, jclass jcaller,
+    jlong ptr);
+
+static jint RenderObjectChildCount(JNIEnv* env, jclass jcaller,
+    jlong ptr);
+
+static jlong RenderObjectGetChild(JNIEnv* env, jclass jcaller,
+    jlong ptr,
+    jint index);
+
+static jlong RenderObjectUpdateComponent(JNIEnv* env, jclass jcaller,
+    jlong ptr,
+    jobject component);
+
+static void RenderObjectChildWaste(JNIEnv* env, jclass jcaller,
+    jlong ptr,
+    jboolean waster);
+
+// Step 2: method stubs.
+
+static intptr_t g_NativeRenderObjectUtils_updateComponentSize = 0;
+static void Java_NativeRenderObjectUtils_updateComponentSize(JNIEnv* env,
+    jobject component,
+    jfloat top,
+    jfloat bottom,
+    jfloat left,
+    jfloat right,
+    jfloat height,
+    jfloat width) {
+  /* Must call RegisterNativesImpl()  */
+  //CHECK_CLAZZ(env, NativeRenderObjectUtils_clazz(env),
+  //    NativeRenderObjectUtils_clazz(env));
+  jmethodID method_id =
+      base::android::GetMethod(
+      env, NativeRenderObjectUtils_clazz(env),
+      base::android::STATIC_METHOD,
+      "updateComponentSize",
+
+"("
+"Lcom/taobao/weex/ui/component/WXComponent;"
+"F"
+"F"
+"F"
+"F"
+"F"
+"F"
+")"
+"V",
+      &g_NativeRenderObjectUtils_updateComponentSize);
+
+     env->CallStaticVoidMethod(NativeRenderObjectUtils_clazz(env),
+          method_id, component, top, bottom, left, right, height, width);
+  base::android::CheckException(env);
+
+}
+
+// Step 3: RegisterNatives.
+
+static const JNINativeMethod kMethodsNativeRenderObjectUtils[] = {
+    { "nativeGetRenderObject",
+"("
+"Ljava/lang/String;"
+"Ljava/lang/String;"
+")"
+"J", reinterpret_cast<void*>(GetRenderObject) },
+    { "nativeUpdateRenderObjectStyle",
+"("
+"J"
+"Ljava/lang/String;"
+"Ljava/lang/String;"
+")"
+"V", reinterpret_cast<void*>(UpdateRenderObjectStyle) },
+    { "nativeUpdateRenderObjectAttr",
+"("
+"J"
+"Ljava/lang/String;"
+"Ljava/lang/String;"
+")"
+"V", reinterpret_cast<void*>(UpdateRenderObjectAttr) },
+    { "nativeCopyRenderObject",
+"("
+"J"
+")"
+"J", reinterpret_cast<void*>(CopyRenderObject) },
+    { "nativeLayoutRenderObject",
+"("
+"J"
+"F"
+"F"
+")"
+"I", reinterpret_cast<void*>(LayoutRenderObject) },
+    { "nativeAddChildRenderObject",
+"("
+"J"
+"J"
+")"
+"V", reinterpret_cast<void*>(AddChildRenderObject) },
+    { "nativeRenderObjectHasNewLayout",
+"("
+"J"
+")"
+"Z", reinterpret_cast<void*>(RenderObjectHasNewLayout) },
+    { "nativeRenderObjectChildCount",
+"("
+"J"
+")"
+"I", reinterpret_cast<void*>(RenderObjectChildCount) },
+    { "nativeRenderObjectGetChild",
+"("
+"J"
+"I"
+")"
+"J", reinterpret_cast<void*>(RenderObjectGetChild) },
+    { "nativeRenderObjectUpdateComponent",
+"("
+"J"
+"Lcom/taobao/weex/ui/component/WXComponent;"
+")"
+"J", reinterpret_cast<void*>(RenderObjectUpdateComponent) },
+    { "nativeRenderObjectChildWaste",
+"("
+"J"
+"Z"
+")"
+"V", reinterpret_cast<void*>(RenderObjectChildWaste) },
+};
+
+static bool RegisterNativesImpl(JNIEnv* env) {
+
+  g_NativeRenderObjectUtils_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
+      base::android::GetClass(env, kNativeRenderObjectUtilsClassPath).Get()));
+
+  const int kMethodsNativeRenderObjectUtilsSize =
+      
sizeof(kMethodsNativeRenderObjectUtils)/sizeof(kMethodsNativeRenderObjectUtils[0]);
+
+  if (env->RegisterNatives(NativeRenderObjectUtils_clazz(env),
+                           kMethodsNativeRenderObjectUtils,
+                           kMethodsNativeRenderObjectUtilsSize) < 0) {
+    //jni_generator::HandleRegistrationError(
+    //    env, NativeRenderObjectUtils_clazz(env), __FILE__);
+    return false;
+  }
+
+  return true;
+}
+
+#endif  // 
com_taobao_weex_ui_component_list_template_jni_NativeRenderObjectUtils_JNI

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b049f80e/weex_core/Source/android/jniprebuild/jniheader/WXBridge_jni.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/android/jniprebuild/jniheader/WXBridge_jni.h 
b/weex_core/Source/android/jniprebuild/jniheader/WXBridge_jni.h
index c3b99c3..201799f 100644
--- a/weex_core/Source/android/jniprebuild/jniheader/WXBridge_jni.h
+++ b/weex_core/Source/android/jniprebuild/jniheader/WXBridge_jni.h
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 // This file is autogenerated by
-//     
weex_core_debug/Source/WeexCore/platform/android/jniprebuild/jni_generator.py
+//     weex-core2/weex_core/Source/android/jniprebuild/jni_generator.py
 // For
 //     com/taobao/weex/bridge/WXBridge
 
@@ -73,6 +73,10 @@ static void BindMeasurementToWXCore(JNIEnv* env, jobject 
jcaller,
     jstring ref,
     jobject contentBoxMeasurement);
 
+static void BindMeasurementToRenderObject(JNIEnv* env, jobject jcaller,
+    jlong ptr,
+    jobject contentBoxMeasurement);
+
 static void SetRenderContainerWrapContent(JNIEnv* env, jobject jcaller,
     jboolean wrap,
     jstring instanceId);
@@ -218,6 +222,12 @@ static const JNINativeMethod kMethodsWXBridge[] = {
 "Lcom/taobao/weex/layout/ContentBoxMeasurement;"
 ")"
 "V", reinterpret_cast<void*>(BindMeasurementToWXCore) },
+    { "nativeBindMeasurementToRenderObject",
+"("
+"J"
+"Lcom/taobao/weex/layout/ContentBoxMeasurement;"
+")"
+"V", reinterpret_cast<void*>(BindMeasurementToRenderObject) },
     { "nativeSetRenderContainerWrapContent",
 "("
 "Z"

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b049f80e/weex_core/Source/android/jniprebuild/prebuild.sh
----------------------------------------------------------------------
diff --git a/weex_core/Source/android/jniprebuild/prebuild.sh 
b/weex_core/Source/android/jniprebuild/prebuild.sh
index a496821..c7db1fe 100755
--- a/weex_core/Source/android/jniprebuild/prebuild.sh
+++ b/weex_core/Source/android/jniprebuild/prebuild.sh
@@ -1,6 +1,6 @@
 #!/bin/bash
 CURRENT_PATH=$(cd `dirname $0`; pwd)
-ROOT_WEEX_JAVA_PATH=$CURRENT_PATH"../../../../android/sdk/src/main/java/"
+ROOT_WEEX_JAVA_PATH=$CURRENT_PATH"/../../../../android/sdk/src/main/java/"
 WEEX_OUTPUT_DIR=$CURRENT_PATH"/jniheader/"
 WEEX_GEN_FILE=$CURRENT_PATH"/jni_generator.py"
 while read line

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b049f80e/weex_core/Source/core/bridge/bridge.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/bridge/bridge.h 
b/weex_core/Source/core/bridge/bridge.h
index 9261445..4494ac5 100644
--- a/weex_core/Source/core/bridge/bridge.h
+++ b/weex_core/Source/core/bridge/bridge.h
@@ -74,7 +74,8 @@ namespace WeexCore {
                                std::set<std::string> *events,
                                const WXCoreMargin &margins,
                                const WXCorePadding &paddings,
-                               const WXCoreBorderWidth &borders) = 0;
+                               const WXCoreBorderWidth &borders,
+                               bool willLayout= true) = 0;
 
     virtual int callLayout(const char* pageId, const char* ref,
                            int top, int bottom, int left, int right,

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b049f80e/weex_core/Source/core/layout/layout.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/layout/layout.h 
b/weex_core/Source/core/layout/layout.h
index 7d50fe8..4233896 100644
--- a/weex_core/Source/core/layout/layout.h
+++ b/weex_core/Source/core/layout/layout.h
@@ -261,6 +261,10 @@ namespace WeexCore {
       }
     }
 
+    void copyFrom(WXCoreLayoutNode* srcNode){
+      memcpy(mCssStyle, srcNode->mCssStyle, sizeof(WXCoreCSSStyle));
+    }
+
     inline void copyMeasureFunc(WXCoreLayoutNode *srcNode) {
       if (memcmp(&measureFunc, &srcNode->measureFunc, 
sizeof(WXCoreMeasureFunc)) != 0) {
         memcpy(&measureFunc, &srcNode->measureFunc, sizeof(WXCoreMeasureFunc));
@@ -673,6 +677,14 @@ namespace WeexCore {
       return mChildList.cend();
     }
 
+    inline bool hasChild(const WXCoreLayoutNode* const child){
+       if(std::find(mChildList.begin(), mChildList.end(), child) != 
mChildList.end()){
+         return true;
+       }else{
+         return false;
+       }
+    }
+
     inline void removeChild(const WXCoreLayoutNode* const child) {
       for (int index = 0; index < mChildList.size(); index++) {
         if (child == mChildList[index]) {
@@ -708,6 +720,10 @@ namespace WeexCore {
       return mParent;
     }
 
+    inline void setParent(WXCoreLayoutNode * const parent, WXCoreLayoutNode * 
const child) const {
+       child->mParent = parent;
+    }
+
     inline bool isBFC(WXCoreLayoutNode* const node) const {
       return node->mCssStyle->mPositionType == kAbsolute || 
node->mCssStyle->mPositionType == kFixed;
     }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b049f80e/weex_core/Source/core/parser/dom_parser.cpp
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/parser/dom_parser.cpp 
b/weex_core/Source/core/parser/dom_parser.cpp
index b2b126f..89aac39 100644
--- a/weex_core/Source/core/parser/dom_parser.cpp
+++ b/weex_core/Source/core/parser/dom_parser.cpp
@@ -22,7 +22,6 @@
 #include <core/render/node/render_object.h>
 #include <core/render/page/render_page.h>
 #include <core/render/node/factory/render_creator.h>
-#include <android/base/log_utils.h>
 
 using namespace std;
 using namespace rapidjson;
@@ -43,6 +42,26 @@ namespace WeexCore {
     return num;
   }
 
+  static inline int GetSplitIndex(std::string temp, const char * leftChar, 
const char * rightChar){
+    int endIndex = temp.find(rightChar);
+    if(endIndex > 0) {
+      // has found!
+      int temp_length = temp.length();
+      int startIndex = 0;
+      int leftMatchSize = matchNum(temp, leftChar, startIndex, endIndex) - 1;
+      while (leftMatchSize > 0 && startIndex <= endIndex && startIndex < 
temp_length) {
+        startIndex = endIndex + 1;
+        int markIndex = temp.find(rightChar, startIndex);
+        if(markIndex > 0) {
+          endIndex = markIndex;
+          leftMatchSize--;
+        }
+        leftMatchSize += matchNum(temp, leftChar, startIndex, endIndex);
+      }
+    }
+    return endIndex;
+  }
+
   bool JsonParserHandler::Null() {
     st_ = kHasNull;
     v_.SetNull();
@@ -240,6 +259,22 @@ namespace WeexCore {
     return result;
   }
 
+  const std::string JsonParser::GetObjectStr() {
+      std::string temp = "{";
+      temp.append(Stringify());
+      int endIndex = GetSplitIndex(temp, "{", "}");
+      SkipValue();
+      return temp.substr(0, endIndex + 1);
+  }
+
+  const std::string JsonParser::GetArrayStr() {
+      std::string temp = "[";
+      temp.append(Stringify());
+      int endIndex = GetSplitIndex(temp, "[", "]");
+      SkipValue();
+      return temp.substr(0, endIndex + 1);
+  }
+
   const char *JsonParser::Stringify() {
     return ss_.src_;
   }
@@ -362,30 +397,12 @@ namespace WeexCore {
             }
           } else if (r.PeekType() == kArrayType) {
             RAPIDJSON_ASSERT(r.PeekType() == kArrayType);
-            std::string temp = "[";
-            temp.append(r.Stringify());
-              int endIndex = temp.find(']');
-              if(endIndex > 0) {
-                  // has found!
-                  int startIndex = 0;
-                  int leftMatchSize = matchNum(temp, "[", startIndex, 
endIndex) - 1;
-                  while (leftMatchSize > 0 && startIndex < endIndex) {
-                      startIndex = endIndex + 1;
-                      int markIndex = temp.find(']', startIndex);
-                      if(markIndex > 0) {
-                          endIndex = markIndex;
-                          leftMatchSize--;
-                      }
-                      leftMatchSize += matchNum(temp, "[", startIndex, 
endIndex);
-                  }
-              }
-            std::string value = temp.substr(0, endIndex + 1);
+            std::string value = r.GetArrayStr();
             if (0 == strcmp(key, "attr")) {
               render->AddAttr(key2, value);
             } else if (0 == strcmp(key, "style")) {
               render->AddStyle(key2, value);
             }
-            r.SkipValue();
           } else if (r.PeekType() == kTrueType) {
             RAPIDJSON_ASSERT(r.PeekType() == kTrueType);
             if (0 == strcmp(key, "attr")) {
@@ -404,47 +421,40 @@ namespace WeexCore {
             r.SkipValue();
           } else if (r.PeekType() == kObjectType) {
             RAPIDJSON_ASSERT(r.PeekType() == kObjectType);
-            std::string temp = "{";
-            temp.append(r.Stringify());
-            int endIndex = temp.find('}');
-            if(endIndex > 0) {
-              // has found!
-              int startIndex = 0;
-              int leftMatchSize = matchNum(temp, "{", startIndex, endIndex) - 
1;
-              while (leftMatchSize > 0 && startIndex < endIndex) {
-                startIndex = endIndex + 1;
-                int markIndex = temp.find('}', startIndex);
-                if(markIndex > 0) {
-                  endIndex = markIndex;
-                  leftMatchSize--;
-                }
-                leftMatchSize += matchNum(temp, "{", startIndex, endIndex);
-              }
-            }
-            std::string value = temp.substr(0, endIndex + 1);
-
+            std::string value = r.GetObjectStr();
             if (0 == strcmp(key, "attr")) {
               render->AddAttr(key2, value);
             } else if (0 == strcmp(key, "style")) {
               render->AddStyle(key2, value);
             }
-            r.SkipValue();
           } else {
             r.SkipValue();
           }
         }
       } else if (0 == strcmp(key, "event")) {
-        RAPIDJSON_ASSERT(r.PeekType() == kArrayType);
-        r.EnterArray();
-        while (r.NextArrayValue()) {
-          RAPIDJSON_ASSERT(r.PeekType() == kStringType);
-          const char *temp_event = r.GetString();
-          render->AddEvent(temp_event);
-          if (temp_event != nullptr) {
-            delete[]temp_event;
-            temp_event = nullptr;
+          if (r.PeekType() == kArrayType) {
+              RAPIDJSON_ASSERT(r.PeekType() == kArrayType);
+              r.EnterArray();
+              while (r.NextArrayValue()) {
+                  std::string temp_event_str;
+                  if(r.PeekType() == kStringType) {
+                      RAPIDJSON_ASSERT(r.PeekType() == kStringType);
+                      const char *temp_event = r.GetString();
+                      temp_event_str.append(temp_event);
+                      delete[]temp_event;
+                  } else if(r.PeekType() == kObjectType){
+                      RAPIDJSON_ASSERT(r.PeekType() == kObjectType);
+                      temp_event_str = r.GetObjectStr();
+                  } else {
+                      r.SkipValue();
+                  }
+
+                  if (temp_event_str.length() > 0) {
+                      render->AddEvent(temp_event_str);
+                  }
+              }
           }
-        }
+
       } else if (0 == strcmp(key, "children")) {
         RAPIDJSON_ASSERT(r.PeekType() == kArrayType);
         r.EnterArray();
@@ -476,7 +486,6 @@ namespace WeexCore {
  * @return {@link RenderObject*}
  */
   RenderObject *Json2RenderObject(char *data, const std::string &pageId) {
-
     JsonParser r(data);
     return ParseJsonObject(r, nullptr, 0, pageId);
   }
@@ -512,27 +521,9 @@ namespace WeexCore {
         }
       } else if (r.PeekType() == kArrayType) {
         RAPIDJSON_ASSERT(r.PeekType() == kArrayType);
-        std::string temp = "[";
-        temp.append(r.Stringify());
-        int endIndex = temp.find(']');
-        if(endIndex > 0) {
-          // has found!
-          int startIndex = 0;
-          int leftMatchSize = matchNum(temp, "[", startIndex, endIndex) - 1;
-          while (leftMatchSize > 0 && startIndex < endIndex) {
-            startIndex = endIndex + 1;
-            int markIndex = temp.find(']', startIndex);
-            if(markIndex > 0) {
-              endIndex = markIndex;
-              leftMatchSize--;
-            }
-            leftMatchSize += matchNum(temp, "[", startIndex, endIndex);
-          }
-        }
-        std::string value = temp.substr(0, endIndex + 1);
+        std::string value = r.GetArrayStr();
         std::pair<std::string, std::string> myPair(key, value);
         pairs->insert(pairs->end(), myPair);
-        r.SkipValue();
       } else if (r.PeekType() == kTrueType) {
         RAPIDJSON_ASSERT(r.PeekType() == kTrueType);
         std::pair<std::string, std::string> myPair(key, "true");
@@ -550,25 +541,7 @@ namespace WeexCore {
         r.SkipValue();
       } else if (r.PeekType() == kObjectType) {
         RAPIDJSON_ASSERT(r.PeekType() == kObjectType);
-        std::string temp = "{";
-        temp.append(r.Stringify());
-        int endIndex = temp.find('}');
-        if(endIndex > 0) {
-          // has found!
-          int startIndex = 0;
-          int leftMatchSize = matchNum(temp, "{", startIndex, endIndex) - 1;
-          while (leftMatchSize > 0 && startIndex < endIndex) {
-            startIndex = endIndex + 1;
-            int markIndex = temp.find('}', startIndex);
-            if(markIndex > 0) {
-              endIndex = markIndex;
-              leftMatchSize--;
-            }
-            leftMatchSize += matchNum(temp, "{", startIndex, endIndex);
-          }
-        }
-        std::string value = temp.substr(0, endIndex + 1);
-
+        std::string value = r.GetObjectStr();
         std::pair<std::string, std::string> myPair(key, value);
         pairs->insert(pairs->end(), myPair);
         r.SkipValue();

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b049f80e/weex_core/Source/core/parser/dom_parser.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/parser/dom_parser.h 
b/weex_core/Source/core/parser/dom_parser.h
index f099ff2..e5ae4be 100644
--- a/weex_core/Source/core/parser/dom_parser.h
+++ b/weex_core/Source/core/parser/dom_parser.h
@@ -111,6 +111,10 @@ namespace WeexCore {
 
     const char *GetString();
 
+    const std::string GetObjectStr();
+
+    const std::string GetArrayStr();
+
     const char *Stringify();
 
     bool GetBool();

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b049f80e/weex_core/Source/core/render/action/render_action_add_element.cpp
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/render/action/render_action_add_element.cpp 
b/weex_core/Source/core/render/action/render_action_add_element.cpp
index c522d41..fd039db 100644
--- a/weex_core/Source/core/render/action/render_action_add_element.cpp
+++ b/weex_core/Source/core/render/action/render_action_add_element.cpp
@@ -21,7 +21,7 @@
 namespace WeexCore {
 
   RenderActionAddElement::RenderActionAddElement(const std::string &pageId, 
const RenderObject *render,
-                                                 const RenderObject *parent, 
int index) {
+                                                 const RenderObject *parent, 
int index, bool willLayout) {
     this->mAttributes = render->Attributes();
     this->mStyles = render->Styles();
     this->mEvents = render->Events();
@@ -33,6 +33,7 @@ namespace WeexCore {
     this->mRef = render->Ref();
     this->mParentRef = parent->Ref();
     this->mIndex = index;
+    this->mWillLayout = willLayout;
   }
 
   void RenderActionAddElement::ExecuteAction() {
@@ -43,7 +44,7 @@ namespace WeexCore {
     long long startTime = getCurrentTime();
     Bridge_Impl_Android::getInstance()->callAddElement(mPageId.c_str(), 
mComponentType.c_str(), mRef.c_str(),
                                                        mIndex, 
mParentRef.c_str(), mStyles, mAttributes,
-                                                       mEvents, mMargins, 
mPaddings, mBorders);
+                                                       mEvents, mMargins, 
mPaddings, mBorders, mWillLayout);
     page->JniCallTime(getCurrentTime() - startTime);
     page->AddElementActionJNITime(getCurrentTime() - startTime);
   }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b049f80e/weex_core/Source/core/render/action/render_action_add_element.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/render/action/render_action_add_element.h 
b/weex_core/Source/core/render/action/render_action_add_element.h
index 4b278c8..25cc8ea 100644
--- a/weex_core/Source/core/render/action/render_action_add_element.h
+++ b/weex_core/Source/core/render/action/render_action_add_element.h
@@ -27,7 +27,7 @@ namespace WeexCore {
 
   public:
     RenderActionAddElement(const std::string &pageId, const RenderObject 
*render, const RenderObject *parent,
-                           int index);
+                           int index, bool willLayout= true);
 
     void ExecuteAction();
 
@@ -43,6 +43,7 @@ namespace WeexCore {
     std::string mParentRef;
     std::string mRef;
     int mIndex;
+    bool mWillLayout;
   };
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b049f80e/weex_core/Source/core/render/node/factory/i_render_object.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/render/node/factory/i_render_object.h 
b/weex_core/Source/core/render/node/factory/i_render_object.h
index e101fc4..6d13569 100644
--- a/weex_core/Source/core/render/node/factory/i_render_object.h
+++ b/weex_core/Source/core/render/node/factory/i_render_object.h
@@ -50,6 +50,13 @@ namespace WeexCore {
       return mType;
     }
 
+    void copyFrom(IRenderObject* src){
+        WXCoreLayoutNode::copyFrom(src);
+        SetRef(src->Ref());
+        SetPageId(src->PageId());
+        SetType(src->Type());
+    }
+
   private:
     std::string mPageId = "";
     std::string mRef = "";

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b049f80e/weex_core/Source/core/render/node/factory/render_creator.cpp
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/render/node/factory/render_creator.cpp 
b/weex_core/Source/core/render/node/factory/render_creator.cpp
index 6660dfb..7318d40 100644
--- a/weex_core/Source/core/render/node/factory/render_creator.cpp
+++ b/weex_core/Source/core/render/node/factory/render_creator.cpp
@@ -40,13 +40,15 @@ namespace WeexCore {
     IRenderFactory *factory;
     if (type == kRenderText) {
       factory = new RenderTextFactory();
-    } else if (type == kRenderCell || type == kRenderHeader) {
+    } else if (type == kRenderCell
+               || type == kRenderHeader
+               || type == kRenderCellSlot) {
       factory = new RenderCellFactory();
     } else if (type == kRenderIndicator) {
       factory = new RenderIndicatorFactory();
     } else if (type == kRenderInput) {
       factory = new RenderInputFactory();
-    } else if (type == kRenderList || type == kRenderWaterfall) {
+    } else if (type == kRenderList || type == kRenderWaterfall || type == 
kRenderRecycleList) {
       factory = new RenderListFactory();
     } else if (type == kRenderMask) {
       factory = new RenderMaskFactory();

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b049f80e/weex_core/Source/core/render/node/factory/render_type.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/render/node/factory/render_type.h 
b/weex_core/Source/core/render/node/factory/render_type.h
index 5a63fb1..aab8245 100644
--- a/weex_core/Source/core/render/node/factory/render_type.h
+++ b/weex_core/Source/core/render/node/factory/render_type.h
@@ -23,10 +23,12 @@
 
 namespace WeexCore {
   constexpr char kRenderCell[] = "cell";
+  constexpr char kRenderCellSlot[] = "cell-slot";
   constexpr char kRenderIndicator[] = "indicator";
   constexpr char kRenderInput[] = "input";
   constexpr char kRenderList[] = "list";
   constexpr char kHList[] = "hlist";
+  constexpr char kRenderRecycleList[] = "recycle-list";
   constexpr char kRenderMask[] = "mask";
   constexpr char kRenderScroller[] = "scroller";
   constexpr char kRenderSwitch[] = "switch";

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b049f80e/weex_core/Source/core/render/node/render_list.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/render/node/render_list.h 
b/weex_core/Source/core/render/node/render_list.h
index e4d4373..2e985bf 100644
--- a/weex_core/Source/core/render/node/render_list.h
+++ b/weex_core/Source/core/render/node/render_list.h
@@ -38,7 +38,45 @@ namespace WeexCore {
     float mAvailableWidth = 0;
     float mColumnGap = COLUMN_GAP_NORMAL;
     bool mIsSetFlex = false;
+    std::vector<RenderObject*> cellSlots;
+    std::vector<RenderObject*> cellSlotsCopys;
+      
+  public:
+      ~RenderList(){
+
+          if(cellSlotsCopys.size() > 0){
+              for(auto it = cellSlotsCopys.begin(); it != 
cellSlotsCopys.end(); ++it){
+                  RenderObject* child =  *it;
+                  if(child){
+                      delete child;
+                      child = nullptr;
+                  }
+              }
+              cellSlotsCopys.clear();
+          }
 
+          if(cellSlots.size() > 0){
+              for(auto it = cellSlots.begin(); it != cellSlots.end(); ++it){
+                  RenderObject* child =  *it;
+                  if(child){
+                      delete child;
+                      child = nullptr;
+                  }
+              }
+              cellSlots.clear();
+          }
+      }
+      
+  public:
+      void addCellSlotCopyTrack(RenderObject* cellSlot){
+          cellSlot->setParent(this, cellSlot);
+          cellSlotsCopys.push_back(cellSlot);
+      }
+      
+      std::vector<RenderObject*> &CellSlots(){
+          return cellSlots;
+      }
+      
     std::map<std::string, std::string> *GetDefaultStyle() {
       std::map<std::string, std::string> *style = new std::map<std::string, 
std::string>();
 
@@ -117,10 +155,11 @@ namespace WeexCore {
             }
 
             mIsPreCalculateCellWidth = true;
-            attrs->insert(std::pair<std::string, std::string>(COLUMN_COUNT, 
std::to_string(mColumnCount)));
-            attrs->insert(std::pair<std::string, std::string>(COLUMN_WIDTH, 
std::to_string(mColumnWidth)));
-            attrs->insert(std::pair<std::string, std::string>(COLUMN_GAP, 
std::to_string(mColumnGap)));
-
+            if(getColumnCount() > 0 || getColumnWidth() > 0 || mColumnCount > 
COLUMN_COUNT_NORMAL){
+                attrs->insert(std::pair<std::string, 
std::string>(COLUMN_COUNT, std::to_string(mColumnCount)));
+                attrs->insert(std::pair<std::string, std::string>(COLUMN_GAP, 
std::to_string(mColumnGap)));
+                attrs->insert(std::pair<std::string, 
std::string>(COLUMN_WIDTH, std::to_string(mColumnWidth)));
+            }
         }
         return attrs;
     }
@@ -143,36 +182,57 @@ namespace WeexCore {
 
 
     int AddRenderObject(int index, RenderObject *child) {
-      index = RenderObject::AddRenderObject(index, child);
+        if(Type() == kRenderRecycleList
+                && (child->Type() == kRenderCellSlot ||  child->Type() == 
kRenderCell || child->Type()  == kRenderHeader)){
+            child->setParent(this, child);
+            cellSlots.insert(cellSlots.end(), child);
+            index = -1;
+        }else{
+            index = RenderObject::AddRenderObject(index, child);
+        }
 
-      if (!mIsPreCalculateCellWidth) {
-        preCalculateCellWidth();
-      }
+        if (!mIsPreCalculateCellWidth) {
+            preCalculateCellWidth();
+        }
 
-      if(mColumnWidth != 0 && !isnan(mColumnWidth)) {
-        //LOGE("listen child->ApplyStyle %s %s", child->Ref().c_str(), 
std::to_string(mColumnWidth).c_str());
-        AddRenderObjectWidth(child, false);
-      }
-      return index;
+        if(mColumnWidth != 0 && !isnan(mColumnWidth)) {
+            //LOGE("listen child->ApplyStyle %s %s", child->Ref().c_str(), 
std::to_string(mColumnWidth).c_str());
+            AddRenderObjectWidth(child, false);
+        }
+        return index;
     }
 
     void AddRenderObjectWidth(RenderObject *child, const bool updating) {
-        if (Type() == kRenderWaterfall) {
+        if (Type() == kRenderWaterfall || Type() == kRenderRecycleList) {
             if(child->Type() == kRenderHeader || child->Type() == 
kRenderFooter) {
                 child->ApplyStyle(WIDTH, std::to_string(mAvailableWidth), 
updating);
-            } else if (child->Type() == kRenderCell){
-                child->ApplyStyle(WIDTH, std::to_string(mColumnWidth), 
updating);
             } else if (child->getStypePositionType() == kSticky) {
                 child->ApplyStyle(WIDTH, std::to_string(GetViewPortWidth()), 
updating);
+            } else if (child->Type() == kRenderCell || child->Type() == 
kRenderCellSlot){
+                child->ApplyStyle(WIDTH, std::to_string(mColumnWidth), 
updating);
             }
         }
     }
 
+    void UpdatePreCalculateCellAttrs(std::map<std::string, std::string> * 
attrs){
+        if (attrs == nullptr){
+            return;
+        }
+
+        for (auto iter = attrs->cbegin(); iter != attrs->cend(); iter++) {
+            RenderObject::UpdateAttr(iter->first, iter->second);
+        }
+        if (attrs != nullptr) {
+            delete attrs;
+            attrs = nullptr;
+        }
+    }
+
     void UpdateAttr(std::string key, std::string value) {
       RenderObject::UpdateAttr(key, value);
 
       if(!GetAttr(COLUMN_COUNT).empty() || !GetAttr(COLUMN_GAP).empty() || 
!GetAttr(COLUMN_WIDTH).empty()){
-        preCalculateCellWidth();
+          UpdatePreCalculateCellAttrs(preCalculateCellWidth());
 
         if(mColumnWidth == 0 && isnan(mColumnWidth)) {
           return;

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b049f80e/weex_core/Source/core/render/node/render_object.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/render/node/render_object.h 
b/weex_core/Source/core/render/node/render_object.h
index 6aa676b..6fa638c 100644
--- a/weex_core/Source/core/render/node/render_object.h
+++ b/weex_core/Source/core/render/node/render_object.h
@@ -33,6 +33,14 @@
 #include <core/css/constants_value.h>
 #include <android/base/log_utils.h>
 
+
+#define JSON_OBJECT_MARK_CHAR  '{'
+#define JSON_ARRAY_MARK_CHAR  '['
+
+#define convert_render_object_to_long(render)    ((jlong)((intptr_t)render))
+
+#define convert_long_to_render_object(ptr)   ((RenderObject *)((intptr_t)ptr))
+
 namespace WeexCore {
 
   class RenderObject;
@@ -55,7 +63,7 @@ namespace WeexCore {
     friend class RenderPage;
 
 
-  private:
+  public:
     inline void LayoutBefore() {
       if (isDirty()) {
         onLayoutBefore();
@@ -95,6 +103,22 @@ namespace WeexCore {
       return nullptr;
     }
 
+    void copyFrom(RenderObject* src){
+      IRenderObject::copyFrom(src);
+      this->mStyles->insert(src->mStyles->begin(), src->mStyles->end());
+      this->mAttributes->insert(src->mAttributes->begin(), 
src->mAttributes->end());
+      this->mEvents->insert(src->mEvents->begin(), src->mEvents->end());
+    }
+
+    inline void mapInsertOrAssign(std::map<std::string, std::string> 
*targetMap, const std::string& key, const std::string& value) {
+      std::map<std::string, std::string>::iterator it = targetMap->find(key);
+      if(it != targetMap->end()){
+        it->second = value;
+      }else{
+        targetMap->insert({key, value});
+      }
+    }
+
    protected:
     bool UpdateStyle(const std::string key, const std::string value,
                       float fallback, std::function<void(float)> functor){
@@ -126,7 +150,16 @@ namespace WeexCore {
 
     void onLayoutAfter(float width, float height);
 
+
+
     virtual StyleType ApplyStyle(const std::string &key, const std::string 
&value, const bool updating) {
+      bool  insert = false;
+      if(value.length() > 0 && value.at(0) == JSON_OBJECT_MARK_CHAR
+         || value.at(0) == JSON_ARRAY_MARK_CHAR){
+        mapInsertOrAssign(mStyles, key, value);
+        insert = true;
+      }
+
       if (key == ALIGN_ITEMS) {
         setAlignItems(GetWXCoreAlignItem(value));
         return kTypeLayout;
@@ -176,7 +209,7 @@ namespace WeexCore {
         return kTypeLayout;
       } else if (key == POSITION) {
         setStylePositionType(GetWXCorePositionType(value));
-        mStyles->insert(std::pair<std::string, std::string>(key, value));
+        mapInsertOrAssign(mStyles, key, value);
         return kTypeStyle;
       } else if (key == LEFT) {
         UpdateStyle(key, value, NAN, [=](float 
foo){setStylePosition(kPositionEdgeLeft, foo);});
@@ -236,7 +269,9 @@ namespace WeexCore {
         UpdateStyle(key, value, 0, [=](float foo){setPadding(kPaddingBottom, 
foo);});
         return kTypePadding;
       } else {
-        mStyles->insert(std::pair<std::string, std::string>(key, value));
+        if(!insert){
+          mapInsertOrAssign(mStyles, key, value);
+        }
         return kTypeStyle;
       }
     }
@@ -294,11 +329,11 @@ namespace WeexCore {
     }
 
     inline void AddAttr(std::string key, std::string value) {
-      mAttributes->insert(std::pair<std::string, std::string>(key, value));
+      mapInsertOrAssign(mAttributes, key, value);
     }
 
     virtual void UpdateAttr(std::string key, std::string value) {
-      AddAttr(key, value);
+      mapInsertOrAssign(mAttributes, key, value);
     }
 
     virtual StyleType UpdateStyle(std::string key, std::string value) {

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b049f80e/weex_core/Source/core/render/node/render_text.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/render/node/render_text.h 
b/weex_core/Source/core/render/node/render_text.h
index 1354624..165e8a7 100644
--- a/weex_core/Source/core/render/node/render_text.h
+++ b/weex_core/Source/core/render/node/render_text.h
@@ -28,9 +28,6 @@ namespace WeexCore {
     inline void UpdateAttr(std::string key, std::string value) {
       RenderObject::UpdateAttr(key, value);
       markDirty();
-      RenderPage* page = GetRenderPage();
-      if (page != nullptr)
-        GetRenderPage()->Batch();
     }
 
     inline StyleType UpdateStyle(std::string key, std::string value) {

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b049f80e/weex_core/Source/core/render/page/render_page.cpp
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/render/page/render_page.cpp 
b/weex_core/Source/core/render/page/render_page.cpp
index 5139481..6acf8be 100644
--- a/weex_core/Source/core/render/page/render_page.cpp
+++ b/weex_core/Source/core/render/page/render_page.cpp
@@ -34,6 +34,8 @@
 #include <core/render/action/render_action_add_event.h>
 #include <core/render/action/render_action_remove_event.h>
 #include <core/css/constants_value.h>
+#include <core/render/node/factory/render_type.h>
+#include <core/render/node/render_list.h>
 #include "render_page.h"
 #include "core/render/manager/render_manager.h"
 #include "core/render/node/render_object.h"
@@ -366,7 +368,7 @@ namespace WeexCore {
     for (auto iter = attrs->cbegin(); iter != attrs->cend(); iter++) {
       render->UpdateAttr((*iter).first, (*iter).second);
     }
-
+    Batch();
     if (attrs != nullptr) {
       attrs->clear();
       attrs->shrink_to_fit();
@@ -507,22 +509,37 @@ namespace WeexCore {
     }
   }
 
-  void RenderPage::SendAddElementAction(RenderObject *child, RenderObject 
*parent, int index, bool is_recursion) {
+  void RenderPage::SendAddElementAction(RenderObject *child, RenderObject 
*parent, int index, bool is_recursion, bool willLayout) {
     if (child == nullptr || parent == nullptr)
       return;
+    if(parent != nullptr && parent->Type() == WeexCore::kRenderRecycleList){
+        willLayout = false;
+    }
 
-    render_action *action = new RenderActionAddElement(PageId(), child, 
parent, index);
+    render_action *action = new RenderActionAddElement(PageId(), child, 
parent, index, willLayout);
     PostRenderAction(action);
 
     Index i = 0;
     for(auto it = child->ChildListIterBegin(); it != 
child->ChildListIterEnd(); it++) {
       RenderObject* grandson = static_cast<RenderObject*>(*it);
       if (grandson != nullptr) {
-        SendAddElementAction(grandson, child, i, true);
+        SendAddElementAction(grandson, child, i, true, willLayout);
       }
       ++i;
     }
 
+    if(child->Type() == WeexCore::kRenderRecycleList){
+      RenderList* renderList = (RenderList*)child;
+      std::vector<RenderObject*>& cellSlots = renderList->CellSlots();
+      for(auto it = cellSlots.begin(); it != cellSlots.end(); it++) {
+        RenderObject* grandson = static_cast<RenderObject*>(*it);
+        if (grandson != nullptr) {
+          SendAddElementAction(grandson, child, -1, true, willLayout);
+        }
+        ++i;
+      }
+    }
+
     if (!is_recursion && i > 0 && child->IsAppendTree()) {
       SendAppendTreeCreateFinish(child->Ref());
     }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b049f80e/weex_core/Source/core/render/page/render_page.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/core/render/page/render_page.h 
b/weex_core/Source/core/render/page/render_page.h
index c3e1d3f..cffcc99 100644
--- a/weex_core/Source/core/render/page/render_page.h
+++ b/weex_core/Source/core/render/page/render_page.h
@@ -47,7 +47,7 @@ namespace WeexCore {
 
     void SendCreateBodyAction(RenderObject *render);
 
-    void SendAddElementAction(RenderObject *child, RenderObject *parent, int 
index, bool is_recursion);
+    void SendAddElementAction(RenderObject *child, RenderObject *parent, int 
index, bool is_recursion, bool willLayout= true);
 
     void SendRemoveElementAction(const std::string &ref);
 

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b049f80e/weex_core/debug.sh
----------------------------------------------------------------------
diff --git a/weex_core/debug.sh b/weex_core/debug.sh
new file mode 100755
index 0000000..79152ef
--- /dev/null
+++ b/weex_core/debug.sh
@@ -0,0 +1,2 @@
+## show c plus plus crash stack
+adb logcat | $NDK/ndk-stack -sym  
../android/sdk/build/intermediates/cmake/debug/obj/x86

Reply via email to