You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@weex.apache.org by gu...@apache.org on 2017/10/17 08:25:24 UTC

[11/50] incubator-weex git commit: improve textdom and refactor template cache and render function

improve textdom and refactor template cache and render function


Project: http://git-wip-us.apache.org/repos/asf/incubator-weex/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-weex/commit/9e6bee8e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-weex/tree/9e6bee8e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-weex/diff/9e6bee8e

Branch: refs/heads/release-0.16
Commit: 9e6bee8ee2b2340a79874dcd3314195b324024a1
Parents: 772ac33
Author: jianbai.gbj <ji...@alibaba-inc.com>
Authored: Wed Sep 27 11:06:45 2017 +0800
Committer: gurisxie <27...@qq.com>
Committed: Tue Oct 10 12:11:25 2017 +0800

----------------------------------------------------------------------
 .../taobao/weex/bridge/NativeInvokeHelper.java  |   2 +-
 .../main/java/com/taobao/weex/dom/WXAttr.java   |   6 +
 .../com/taobao/weex/dom/WXCellDomObject.java    |  11 +
 .../java/com/taobao/weex/dom/WXDomManager.java  |   4 +
 .../java/com/taobao/weex/dom/WXDomObject.java   |   7 +-
 .../taobao/weex/dom/WXRecyclerDomObject.java    |  47 +-
 .../com/taobao/weex/dom/WXTextDomObject.java    |  31 +-
 .../com/taobao/weex/dom/binding/ELUtils.java    |   2 +
 .../java/com/taobao/weex/dom/flex/CSSNode.java  |  14 +-
 .../taobao/weex/ui/component/WXComponent.java   |  10 +-
 .../weex/ui/component/binding/Layouts.java      |  53 ++-
 .../weex/ui/component/binding/Statements.java   | 103 +++--
 .../ui/component/list/BasicListComponent.java   |   1 -
 .../taobao/weex/ui/component/list/WXCell.java   |  30 ++
 .../list/template/CellLifecycleManager.java     | 211 ---------
 .../component/list/template/DomTreeBuilder.java |  83 ++++
 .../component/list/template/TemplateCache.java  |  30 ++
 .../list/template/TemplateViewHolder.java       |   2 +
 .../list/template/WXRecyclerTemplateList.java   | 443 ++++++++++++-------
 .../ui/component/binding/StatementTest.java     |   8 +-
 20 files changed, 654 insertions(+), 444 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9e6bee8e/android/sdk/src/main/java/com/taobao/weex/bridge/NativeInvokeHelper.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/bridge/NativeInvokeHelper.java b/android/sdk/src/main/java/com/taobao/weex/bridge/NativeInvokeHelper.java
index 98381b5..73255db 100644
--- a/android/sdk/src/main/java/com/taobao/weex/bridge/NativeInvokeHelper.java
+++ b/android/sdk/src/main/java/com/taobao/weex/bridge/NativeInvokeHelper.java
@@ -47,7 +47,7 @@ public final class NativeInvokeHelper {
           try {
             invoker.invoke(target, params);
           } catch (Exception e) {
-            throw new RuntimeException(e);
+            throw new RuntimeException(target + "Invoker " + invoker.toString() ,e);
           }
         }
       }, 0);

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9e6bee8e/android/sdk/src/main/java/com/taobao/weex/dom/WXAttr.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/dom/WXAttr.java b/android/sdk/src/main/java/com/taobao/weex/dom/WXAttr.java
index c3b0399..b05d46d 100644
--- a/android/sdk/src/main/java/com/taobao/weex/dom/WXAttr.java
+++ b/android/sdk/src/main/java/com/taobao/weex/dom/WXAttr.java
@@ -19,6 +19,7 @@
 package com.taobao.weex.dom;
 
 import static com.taobao.weex.dom.binding.ELUtils.COMPONENT_PROPS;
+import static com.taobao.weex.dom.binding.ELUtils.EXCLUDES_BINDING;
 import static java.lang.Boolean.parseBoolean;
 
 import android.support.annotation.NonNull;
@@ -477,6 +478,11 @@ public class WXAttr implements Map<String, Object>,Cloneable {
           ELUtils.bindingBlock(value);
           return  false;
         }
+        for(String exclude : EXCLUDES_BINDING){
+             if(key.equals(exclude)){
+                return  false;
+             }
+        }
         if(ELUtils.isBinding(value)){
           if(mBindingAttrs == null){
               mBindingAttrs = new ArrayMap<String, Object>();

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9e6bee8e/android/sdk/src/main/java/com/taobao/weex/dom/WXCellDomObject.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/dom/WXCellDomObject.java b/android/sdk/src/main/java/com/taobao/weex/dom/WXCellDomObject.java
index 6d50ab6..649a09d 100644
--- a/android/sdk/src/main/java/com/taobao/weex/dom/WXCellDomObject.java
+++ b/android/sdk/src/main/java/com/taobao/weex/dom/WXCellDomObject.java
@@ -41,11 +41,22 @@ public class WXCellDomObject extends WXDomObject {
           if (WXBasicComponentType.CELL.equals(domObject.getType())
                   || WXBasicComponentType.CELL_SLOT.equals(domObject.getType())) {
             float w = ((WXRecyclerDomObject) parent).getColumnWidth();
+            if(w <= 0 && parentDom.getColumnCount() <= 1){
+                  w = parentDom.getAvailableWidth();
+                  if(w <= 0){
+                      w = parentDom.getLayoutWidth();
+                      if(w <= 0){
+                          w = parentDom.getViewPortWidth();
+                      }
+                  }
+             }
             node.setLayoutWidth(w);
+            measureOutput.width  = w;
           } else if (WXBasicComponentType.HEADER.equals(domObject.getType())){
             float w = parentDom.getAvailableWidth();
             WXLogUtils.d("getAvailableWidth:"+w);
             node.setLayoutWidth(w);
+            measureOutput.width  = w;
           }
         }else if (node instanceof  WXCellDomObject){
           WXCellDomObject slotDomObject = (WXCellDomObject) node;

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9e6bee8e/android/sdk/src/main/java/com/taobao/weex/dom/WXDomManager.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/dom/WXDomManager.java b/android/sdk/src/main/java/com/taobao/weex/dom/WXDomManager.java
index 66fd56e..e1ed82f 100644
--- a/android/sdk/src/main/java/com/taobao/weex/dom/WXDomManager.java
+++ b/android/sdk/src/main/java/com/taobao/weex/dom/WXDomManager.java
@@ -178,6 +178,10 @@ public final class WXDomManager {
     }
   }
 
+  public DOMActionContext getDomContext(String instanceId){
+     return mDomRegistries.get(instanceId);
+  }
+
   /**
    *  @param action
    * @param createContext only true when create body

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9e6bee8e/android/sdk/src/main/java/com/taobao/weex/dom/WXDomObject.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/dom/WXDomObject.java b/android/sdk/src/main/java/com/taobao/weex/dom/WXDomObject.java
index 001545d..8398a2d 100644
--- a/android/sdk/src/main/java/com/taobao/weex/dom/WXDomObject.java
+++ b/android/sdk/src/main/java/com/taobao/weex/dom/WXDomObject.java
@@ -136,6 +136,10 @@ public class WXDomObject extends CSSNode implements Cloneable,ImmutableDomObject
     return mRef;
   }
 
+  public void setRef(String ref) {
+    this.mRef = ref;
+  }
+
   public String getType(){
     return mType;
   }
@@ -301,6 +305,7 @@ public class WXDomObject extends CSSNode implements Cloneable,ImmutableDomObject
     }
   }
 
+
   public boolean isFixed() {
     return mStyles == null ? false : mStyles.isFixed();
   }
@@ -459,7 +464,7 @@ public class WXDomObject extends CSSNode implements Cloneable,ImmutableDomObject
     super.dirty();
   }
 
-  /** package **/ void applyStyleToNode() {
+  /** package **/public void applyStyleToNode() {
     WXStyle stylesMap = getStyles();
     int vp = getViewPortWidth();
     if (!stylesMap.isEmpty()) {

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9e6bee8e/android/sdk/src/main/java/com/taobao/weex/dom/WXRecyclerDomObject.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/dom/WXRecyclerDomObject.java b/android/sdk/src/main/java/com/taobao/weex/dom/WXRecyclerDomObject.java
index 1ae3af2..11918e8 100644
--- a/android/sdk/src/main/java/com/taobao/weex/dom/WXRecyclerDomObject.java
+++ b/android/sdk/src/main/java/com/taobao/weex/dom/WXRecyclerDomObject.java
@@ -27,9 +27,11 @@ import com.taobao.weex.ui.component.WXBasicComponentType;
 import com.taobao.weex.utils.WXLogUtils;
 import com.taobao.weex.utils.WXViewUtils;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 import java.util.Map;
 
-import static com.taobao.weex.dom.flex.CSSLayout.DIMENSION_WIDTH;
 
 /**
  * Created by zhengshihan on 2017/2/21.
@@ -43,6 +45,10 @@ public class WXRecyclerDomObject extends WXDomObject{
     private float mAvailableWidth = 0;
     private boolean mIsPreCalculateCellWidth =false;
 
+    /**cell-slot not on the tree */
+    private List<WXCellDomObject> cellList;
+
+
     public float getAvailableWidth() {
         return WXViewUtils.getRealPxByWidth(mAvailableWidth,getViewPortWidth());
     }
@@ -64,9 +70,18 @@ public class WXRecyclerDomObject extends WXDomObject{
     }
     @Override
     public void add(WXDomObject child, int index) {
-        super.add(child, index);
+        if(WXBasicComponentType.CELL_SLOT.equals(child.getType())
+                && child instanceof  WXCellDomObject){
+            if(cellList == null){
+                cellList = Collections.synchronizedList(new ArrayList<WXCellDomObject>());
+            }
+            cellList.add((WXCellDomObject)child);
+        }else{
+            super.add(child, index);
+        }
 
-        if (WXBasicComponentType.CELL.equals(child.getType())) {
+        if (WXBasicComponentType.CELL.equals(child.getType())
+                || WXBasicComponentType.CELL_SLOT.equals(child.getType())) {
             if (!mIsPreCalculateCellWidth) {
                 preCalculateCellWidth();
             }
@@ -77,6 +92,22 @@ public class WXRecyclerDomObject extends WXDomObject{
     }
 
     @Override
+    public void remove(WXDomObject child) {
+        if(cellList != null){
+            cellList.remove(child);
+        }
+        super.remove(child);
+    }
+
+    @Override
+    public void removeFromDom(WXDomObject child) {
+        if(cellList != null){
+            cellList.remove(child);
+        }
+        super.removeFromDom(child);
+    }
+
+    @Override
     public float getStyleWidth() {
         float width =  getLayoutWidth();
         if (Float.isNaN(width) || width <= 0){
@@ -192,4 +223,14 @@ public class WXRecyclerDomObject extends WXDomObject{
         return  Constants.Orientation.VERTICAL;
     }
 
+    @Override
+    public WXDomObject clone() {
+        WXRecyclerDomObject domObject = (WXRecyclerDomObject) super.clone();
+        domObject.cellList = cellList;
+        return domObject;
+    }
+
+    public List<WXCellDomObject> getCellList() {
+        return cellList;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9e6bee8e/android/sdk/src/main/java/com/taobao/weex/dom/WXTextDomObject.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/dom/WXTextDomObject.java b/android/sdk/src/main/java/com/taobao/weex/dom/WXTextDomObject.java
index 3456bde..bdcfd39 100644
--- a/android/sdk/src/main/java/com/taobao/weex/dom/WXTextDomObject.java
+++ b/android/sdk/src/main/java/com/taobao/weex/dom/WXTextDomObject.java
@@ -39,6 +39,8 @@ import android.text.TextUtils;
 import android.text.style.AbsoluteSizeSpan;
 import android.text.style.AlignmentSpan;
 import android.text.style.ForegroundColorSpan;
+import android.util.Log;
+
 import com.taobao.weex.WXEnvironment;
 import com.taobao.weex.common.Constants;
 import com.taobao.weex.common.WXThread;
@@ -98,9 +100,16 @@ public class WXTextDomObject extends WXDomObject {
       if (CSSConstants.isUndefined(width)) {
         width = node.cssstyle.maxWidth;
       }
-      if(textDomObject.getTextWidth(textDomObject.mTextPaint,width,false)>0) {
-        textDomObject.layout = textDomObject.createLayout(width, false, null);
-        textDomObject.hasBeenMeasured = true;
+      boolean forceWidth = false;
+      if(width > 0){
+         if(node.getParent() != null && textDomObject.mAlignment == Layout.Alignment.ALIGN_CENTER){
+            forceWidth = FloatUtil.floatsEqual(width, node.getParent().getLayoutWidth());
+         }
+      }
+      textDomObject.hasBeenMeasured = true;
+      width = textDomObject.getTextWidth(textDomObject.mTextPaint,width, forceWidth);
+      if(width > 0 && textDomObject.mText != null) {
+        textDomObject.layout = textDomObject.createLayout(width, true, null);
         textDomObject.previousWidth = textDomObject.layout.getWidth();
         measureOutput.height = textDomObject.layout.getHeight();
         measureOutput.width = textDomObject.previousWidth;
@@ -186,7 +195,7 @@ public class WXTextDomObject extends WXDomObject {
     hasBeenMeasured = false;
     if (layout != null && !layout.equals(atomicReference.get()) &&
         Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
-      if(Thread.currentThread() instanceof WXThread){
+      if(Thread.currentThread() != Looper.getMainLooper().getThread()){
           warmUpTextLayoutCache(layout);
       }
     }
@@ -241,8 +250,12 @@ public class WXTextDomObject extends WXDomObject {
     float contentWidth = WXDomUtils.getContentWidth(this);
     if (contentWidth > 0) {
       spanned = createSpanned(mText);
-      layout = createLayout(contentWidth, true, layout);
-      previousWidth = layout.getWidth();
+      if(mText != null){
+         layout = createLayout(contentWidth, true, layout);
+         previousWidth = layout.getWidth();
+      }else{
+         previousWidth = 0;
+      }
     }
   }
 
@@ -394,6 +407,12 @@ public class WXTextDomObject extends WXDomObject {
    * outerWidth in case of outerWidth is defined, in other case, it will be outer width.
    */
    float getTextWidth(TextPaint textPaint,float outerWidth, boolean forceToDesired) {
+     if(mText == null){
+       if(forceToDesired){
+         return  outerWidth;
+       }
+        return  0;
+     }
     float textWidth;
     if (forceToDesired) {
       textWidth = outerWidth;

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9e6bee8e/android/sdk/src/main/java/com/taobao/weex/dom/binding/ELUtils.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/dom/binding/ELUtils.java b/android/sdk/src/main/java/com/taobao/weex/dom/binding/ELUtils.java
index c0924f0..8202a46 100644
--- a/android/sdk/src/main/java/com/taobao/weex/dom/binding/ELUtils.java
+++ b/android/sdk/src/main/java/com/taobao/weex/dom/binding/ELUtils.java
@@ -41,6 +41,8 @@ public class ELUtils {
 
     public static final String COMPONENT_PROPS = "@componentProps";
 
+    public static final  String[] EXCLUDES_BINDING = {"clickEventParams"};
+
     /**
      * @param value check object is binding expression
      * */

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9e6bee8e/android/sdk/src/main/java/com/taobao/weex/dom/flex/CSSNode.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/dom/flex/CSSNode.java b/android/sdk/src/main/java/com/taobao/weex/dom/flex/CSSNode.java
index 3f55245..79ba6e5 100755
--- a/android/sdk/src/main/java/com/taobao/weex/dom/flex/CSSNode.java
+++ b/android/sdk/src/main/java/com/taobao/weex/dom/flex/CSSNode.java
@@ -9,6 +9,9 @@ package com.taobao.weex.dom.flex;
 
 import android.support.annotation.NonNull;
 
+import com.taobao.weex.WXEnvironment;
+import com.taobao.weex.utils.WXLogUtils;
+
 import java.util.ArrayList;
 
 import static com.taobao.weex.dom.flex.CSSLayout.DIMENSION_HEIGHT;
@@ -54,6 +57,10 @@ public class CSSNode {
     dirty();
   }
 
+  public void markLayoutStateUpdated(){
+     this.mLayoutState = LayoutState.UP_TO_DATE;
+  }
+
   /**
    * whether layout changed when {@link #updateLastLayout(CSSLayout)} invoked last time.
    * @return
@@ -165,12 +172,15 @@ public class CSSNode {
     if (mLayoutState == LayoutState.DIRTY) {
       return;
     } else if (mLayoutState == LayoutState.HAS_NEW_LAYOUT) {
-      throw new IllegalStateException("Previous csslayout was ignored! markLayoutSeen() never called");
+      if(WXEnvironment.isApkDebugable()){
+          WXLogUtils.w("weex",  new IllegalStateException("Previous csslayout was ignored! markLayoutSeen() never called"));
+      }
+      markLayoutSeen();
     }
 
     mLayoutState = LayoutState.DIRTY;
 
-    if (mParent != null) {
+    if (mParent != null && !mParent.isDirty()) {
       mParent.dirty();
     }
   }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9e6bee8e/android/sdk/src/main/java/com/taobao/weex/ui/component/WXComponent.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXComponent.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXComponent.java
index e9d7296..f735e4e 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXComponent.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXComponent.java
@@ -337,7 +337,7 @@ public abstract class  WXComponent<T extends View> implements IWXObject, IWXActi
     long startNanos = System.nanoTime();
     if(!isLazy()) {
       if (component == null) {
-        component = this;
+          component = this;
       }
       setLayout(component.getDomObject());
       setPadding(component.getDomObject().getPadding(), component.getDomObject().getBorder());
@@ -1408,6 +1408,14 @@ public abstract class  WXComponent<T extends View> implements IWXObject, IWXActi
         view.setVisibility(View.GONE);
       }
     }
+    if(mDomObj != null){
+      WXDomObject domObject = (WXDomObject) mDomObj;
+      if (TextUtils.equals(visibility, Constants.Value.VISIBLE)) {
+          domObject.setVisible(true);
+      } else if (TextUtils.equals(visibility, Constants.Value.HIDDEN)) {
+          domObject.setVisible(false);
+      }
+    }
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9e6bee8e/android/sdk/src/main/java/com/taobao/weex/ui/component/binding/Layouts.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/binding/Layouts.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/binding/Layouts.java
index 5b8d32c..1e48ea7 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/binding/Layouts.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/binding/Layouts.java
@@ -28,9 +28,11 @@ import com.taobao.weex.WXSDKInstance;
 import com.taobao.weex.common.Constants;
 import com.taobao.weex.dom.WXDomObject;
 import com.taobao.weex.dom.flex.CSSLayoutContext;
+import com.taobao.weex.dom.flex.CSSNode;
 import com.taobao.weex.ui.component.WXComponent;
 import com.taobao.weex.ui.component.WXVContainer;
 import com.taobao.weex.ui.component.list.template.TemplateViewHolder;
+import com.taobao.weex.ui.component.list.template.WXRecyclerTemplateList;
 import com.taobao.weex.utils.WXLogUtils;
 
 /**
@@ -41,35 +43,41 @@ public class Layouts {
      * do dom layout async or sync , and set layout to component on main.
      * on first use do sync layout, when compontnet reuse do async layout
      * */
-    public static void doLayoutAsync(final TemplateViewHolder templateViewHolder){
+    public static void doLayoutAsync(final TemplateViewHolder templateViewHolder, boolean async){
         final WXComponent component = templateViewHolder.getComponent();
         final  int position = templateViewHolder.getHolderPosition();
         if(templateViewHolder.asyncTask != null){
-            templateViewHolder.asyncTask.cancel(true);
+            templateViewHolder.asyncTask.cancel(false);
             templateViewHolder.asyncTask = null;
         }
-        AsyncTask<Void, Void, Void> asyncTask = new AsyncTask<Void, Void, Void>() {
-            @Override
-            protected Void doInBackground(Void... params) {
-                if(templateViewHolder.getHolderPosition() == position){
-                    if(component.getInstance() != null && !component.getInstance().isDestroy()) {
-                        doSafeLayout(component, templateViewHolder.getLayoutContext());
+        if(async){
+            AsyncTask<Void, Void, Void> asyncTask = new AsyncTask<Void, Void, Void>() {
+                @Override
+                protected Void doInBackground(Void... params) {
+                    if(templateViewHolder.getHolderPosition() == position){
+                        if(component.getInstance() != null && !component.getInstance().isDestroy()) {
+                            doSafeLayout(component, templateViewHolder.getLayoutContext());
+                        }
                     }
+                    return null;
                 }
-                return null;
-            }
 
-            @Override
-            protected void onPostExecute(Void aVoid) {
-                if(position == templateViewHolder.getHolderPosition()) {
-                    if(component.getInstance() != null && !component.getInstance().isDestroy()) {
-                        setLayout(component, false);
+                @Override
+                protected void onPostExecute(Void aVoid) {
+                    if(position == templateViewHolder.getHolderPosition()) {
+                        if(component.getInstance() != null && !component.getInstance().isDestroy()) {
+                            setLayout(component, false);
+                        }
                     }
                 }
-            }
-        };
-        templateViewHolder.asyncTask = asyncTask;
-        asyncTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR); //serial executor is better
+            };
+            templateViewHolder.asyncTask = asyncTask;
+            asyncTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR); //serial executor is better
+        }else{
+            doSafeLayout(component, templateViewHolder.getLayoutContext());
+            Log.e("weex", "weex" + component.getLayoutHeight() + "  " + component.getLayoutWidth());
+            setLayout(component, false);
+        }
 
     }
 
@@ -81,13 +89,13 @@ public class Layouts {
             long start = System.currentTimeMillis();
             doLayout(component, layoutContext);
             if(WXEnvironment.isApkDebugable()){
-                WXLogUtils.d("WXTemplateList",
+                WXLogUtils.d(WXRecyclerTemplateList.TAG, "WXTemplateList doSafeLayout" +
                         component.getDomObject().getAttrs().get(Constants.Name.Recycler.SLOT_TEMPLATE_TYPE) + Thread.currentThread().getName() +  " doSafeLayout  used " +
                                 (System.currentTimeMillis() - start));
             }
         }catch (Exception e){
             if(WXEnvironment.isApkDebugable()){
-                WXLogUtils.e("WXTemplateListdoSafeLayout",  e);
+                WXLogUtils.e(WXRecyclerTemplateList.TAG, e);
             }
         }
     }
@@ -135,6 +143,9 @@ public class Layouts {
         WXDomObject domObject = (WXDomObject) component.getDomObject();
         if(domObject.hasUpdate() || force){
             domObject.markUpdateSeen();
+            if(domObject.hasUpdate()){
+                domObject.markLayoutStateUpdated();
+            }
             component.setLayout(component.getDomObject());
             if(component.getDomObject().getExtra() != null){
                 component.updateExtra(component.getDomObject().getExtra());

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9e6bee8e/android/sdk/src/main/java/com/taobao/weex/ui/component/binding/Statements.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/binding/Statements.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/binding/Statements.java
index 6912335..1af8934 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/binding/Statements.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/binding/Statements.java
@@ -25,6 +25,8 @@ import android.util.Log;
 
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
+import com.taobao.weex.WXEnvironment;
+import com.taobao.weex.annotation.Component;
 import com.taobao.weex.common.Constants;
 import com.taobao.weex.dom.WXAttr;
 import com.taobao.weex.dom.WXDomObject;
@@ -39,6 +41,8 @@ import com.taobao.weex.ui.component.WXComponent;
 import com.taobao.weex.ui.component.WXComponentFactory;
 import com.taobao.weex.ui.component.WXImage;
 import com.taobao.weex.ui.component.WXVContainer;
+import com.taobao.weex.ui.component.list.WXCell;
+import com.taobao.weex.ui.component.list.template.WXRecyclerTemplateList;
 import com.taobao.weex.utils.WXLogUtils;
 import com.taobao.weex.utils.WXUtils;
 
@@ -59,7 +63,11 @@ public class Statements {
      * recursive copy component, none parent connect
      * */
     public static WXComponent copyComponentTree(WXComponent component){
+        long start = System.currentTimeMillis();
         WXComponent copy =  copyComponentTree(component, component.getParent());
+        if(WXEnvironment.isApkDebugable()){
+            WXLogUtils.d(WXRecyclerTemplateList.TAG, Thread.currentThread() + component.getRef() + "copyComponentTree " + "used " + (System.currentTimeMillis() - start));
+        }
         return copy;
     }
 
@@ -96,26 +104,47 @@ public class Statements {
      *  may be next render it can be used.
      *  after statement has executed, render component's binding attrs in context and bind it to component.
      * */
-    public static final void doRender(WXComponent component, ArrayStack stack){
+    public static final List<WXComponent> doRender(WXComponent component, ArrayStack stack){
+        List<WXComponent> updates = new ArrayList<>(4);
         try{
-            doRenderComponent(component, stack);
+            doRenderComponent(component, stack, updates);
         }catch (Exception e){
             WXLogUtils.e("WeexStatementRender", e);
         }
+        return updates;
     }
 
+    public static final void doInitCompontent(List<WXComponent> updates) {
+        if(updates == null || updates.size() == 0){
+            return;
+        }
+        for(WXComponent renderNode : updates){
+            if(renderNode.getParent() == null){
+                throw new IllegalArgumentException("render node parent cann't find");
+            }
+            WXVContainer parent = renderNode.getParent();
+            int renderIndex = parent.indexOf(renderNode);
+            if(renderIndex < 0){
+                throw new IllegalArgumentException("render node cann't find");
+            }
+            parent.createChildViewAt(renderIndex);
+            renderNode.applyLayoutAndEvent(renderNode);
+            renderNode.bindData(renderNode);
+        }
+    }
 
-    /**
-     *  @param component component with v-for statement, v-if statement and bind attrs
-     *  @param context   execute context
-     *  render component in context, the function do the following  work.
-     *  execute component's v-for statement, v-if statement in context,
-     *  and rebuild component's tree with the statement, v-for reuse component execute by pre render.
-     *  if executed, component will be removed, don't remove, just mark it waste;
-     *  may be next render it can be used.
-     *  after statement has executed, render component's binding attrs in context and bind it to component.
-     * */
-    static final int doRenderComponent(WXComponent component, ArrayStack context){
+        /**
+         *  @param component component with v-for statement, v-if statement and bind attrs
+         *  @param context   execute context
+         *  render component in context, the function do the following  work.
+         *  execute component's v-for statement, v-if statement in context,
+         *  and rebuild component's tree with the statement, v-for reuse component execute by pre render.
+         *  if executed, component will be removed, don't remove, just mark it waste;
+         *  may be next render it can be used.
+         *  after statement has executed, render component's binding attrs in context and bind it to component.
+         * */
+    private static final int doRenderComponent(WXComponent component, ArrayStack context,
+                                       List<WXComponent> updates){
         WXVContainer parent = component.getParent();
         WXDomObject domObject = (WXDomObject) component.getDomObject();
         WXAttr attrs = domObject.getAttrs();
@@ -198,18 +227,18 @@ public class Statements {
                             }
                             //none resuable render node, create node, add to parent, but clear node's statement
                             if(renderNode == null){
+                                long start = System.currentTimeMillis();
                                 renderNode = copyComponentTree(component, parent);
                                 WXDomObject renderNodeDomObject = (WXDomObject) renderNode.getDomObject();
                                 renderNodeDomObject.getAttrs().setStatement(null); // clear node's statement
                                 parentDomObject.add(renderNodeDomObject, renderIndex);
                                 parent.addChild(renderNode, renderIndex);
-                                if(Thread.currentThread() == Looper.getMainLooper().getThread()) {
-                                    parent.createChildViewAt(renderIndex);
-                                    renderNode.applyLayoutAndEvent(renderNode);
-                                    renderNode.bindData(renderNode);
+                                updates.add(renderNode);
+                                if(WXEnvironment.isApkDebugable()){
+                                    WXLogUtils.d(WXRecyclerTemplateList.TAG, Thread.currentThread().getName() +  renderNode.getRef() + renderNode.getDomObject().getType() + "statements copy component tree used " + (System.currentTimeMillis() - start));
                                 }
                             }
-                            doBindingAttrsEventAndRenderChildNode(renderNode, domObject, context);
+                            doBindingAttrsEventAndRenderChildNode(renderNode, domObject, context, updates);
                             renderIndex++;
                             if(loop.size() > 0){
                                 context.push(loop);
@@ -220,7 +249,7 @@ public class Statements {
                         }
                     }
                 }else{
-                    WXLogUtils.e("StatementsVFor",  vfor.toJSONString() + " not call vfor block, for pre compile");
+                    WXLogUtils.e(WXRecyclerTemplateList.TAG,  vfor.toJSONString() + " not call vfor block, for pre compile");
                 }
                 //after v-for execute, remove component created pre v-for.
                 for(;renderIndex<parent.getChildCount(); renderIndex++){
@@ -237,20 +266,23 @@ public class Statements {
             if(vif != null){
                 if(!Operators.isTrue(vif.execute(context))){
                     component.setWaste(true);
-                    return 1;
+                    if(Thread.currentThread() == Looper.getMainLooper().getThread()) {
+                        return 1;
+                    }
                 }else{
                     component.setWaste(false);
                 }
             }
         }
-        doBindingAttrsEventAndRenderChildNode(component, domObject, context);
+        doBindingAttrsEventAndRenderChildNode(component, domObject, context, updates);
         return  1;
     }
 
     /**
      * bind attrs and doRender component child
      * */
-    private static void doBindingAttrsEventAndRenderChildNode(WXComponent component, WXDomObject domObject, ArrayStack context){
+    private static void doBindingAttrsEventAndRenderChildNode(WXComponent component, WXDomObject domObject, ArrayStack context,
+                                                              List<WXComponent> updates){
        WXAttr attr = component.getDomObject().getAttrs();
         /**
          * sub component supported, sub component new stack
@@ -266,10 +298,17 @@ public class Statements {
         }
         doRenderBindingAttrsAndEvent(component, domObject, context);
         if(component instanceof WXVContainer){
+            if(!domObject.isShow()){
+                if(!(component instanceof WXCell)){
+                    if(Thread.currentThread() == Looper.getMainLooper().getThread()){
+                        return;
+                    }
+                }
+            }
             WXVContainer container = (WXVContainer) component;
             for(int k=0; k<container.getChildCount();){
                 WXComponent next = container.getChild(k);
-                k += doRenderComponent(next, context);
+                k += doRenderComponent(next, context, updates);
             }
         }
     }
@@ -325,6 +364,7 @@ public class Statements {
                 if(Thread.currentThread() == Looper.getMainLooper().getThread()) {
                     component.updateProperties(dynamic);
                 }
+                dynamic.clear();
             }
         }
         WXEvent event = domObject.getEvents();
@@ -346,9 +386,16 @@ public class Statements {
      * @param  context  context
      * return binding attrs rended value in context
      * */
+    private static final  ThreadLocal<Map<String, Object>> dynamicLocal = new ThreadLocal<>();
     public static Map<String, Object> renderBindingAttrs(ArrayMap bindAttrs, ArrayStack context){
         Set<Map.Entry<String, Object>> entrySet = bindAttrs.entrySet();
-        Map<String, Object> dynamic = new HashMap<>();
+        Map<String, Object> dynamic = dynamicLocal.get();
+        if(dynamic == null) {
+            dynamic = new HashMap<>();
+        }
+        if(dynamic.size() > 0){
+            dynamic.clear();
+        }
         for(Map.Entry<String, Object> entry : entrySet){
             Object value = entry.getValue();
             String key = entry.getKey();
@@ -378,7 +425,13 @@ public class Statements {
                         builder.append(blockValue);
                     }
                 }
-                dynamic.put(key, builder.toString());
+                String builderString = builder.toString();
+                if(builderString.length() > 256){
+                    if(WXEnvironment.isApkDebugable()){
+                        WXLogUtils.w(WXRecyclerTemplateList.TAG, " warn too big string " + builderString);
+                    }
+                }
+                dynamic.put(key, builderString);
             }
         }
         return  dynamic;

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9e6bee8e/android/sdk/src/main/java/com/taobao/weex/ui/component/list/BasicListComponent.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/BasicListComponent.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/BasicListComponent.java
index 9b8fe04..640a17e 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/BasicListComponent.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/BasicListComponent.java
@@ -459,7 +459,6 @@ public abstract class BasicListComponent<T extends ViewGroup & ListComponentView
         //Invalid position
         return;
       }
-
       final WXRecyclerView view = bounceRecyclerView.getInnerView();
       view.scrollTo(smooth, pos, offset, getOrientation());
     }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9e6bee8e/android/sdk/src/main/java/com/taobao/weex/ui/component/list/WXCell.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/WXCell.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/WXCell.java
index 401b654..4fe4bc2 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/WXCell.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/WXCell.java
@@ -55,6 +55,12 @@ public class WXCell extends WidgetContainer<WXFrameLayout> {
     private int mScrollPositon = -1;
     private boolean mFlatUIEnabled = false;
 
+    private Object  renderData;
+
+    private boolean isSourceUsed = false;
+
+    private boolean hasLayout = false;
+
     @Deprecated
     public WXCell(WXSDKInstance instance, WXDomObject dom, WXVContainer parent, String instanceId, boolean isLazy) {
         super(instance, dom, parent);
@@ -178,4 +184,28 @@ public class WXCell extends WidgetContainer<WXFrameLayout> {
     public boolean intendToBeFlatContainer() {
         return getInstance().getFlatUIContext().isFlatUIEnabled(this) && WXCell.class.equals(getClass()) && !isSticky();
     }
+
+    public Object getRenderData() {
+        return renderData;
+    }
+
+    public void setRenderData(Object renderData) {
+        this.renderData = renderData;
+    }
+
+    public boolean isSourceUsed() {
+        return isSourceUsed;
+    }
+
+    public void setSourceUsed(boolean sourceUsed) {
+        isSourceUsed = sourceUsed;
+    }
+
+    public boolean isHasLayout() {
+        return hasLayout;
+    }
+
+    public void setHasLayout(boolean hasLayout) {
+        this.hasLayout = hasLayout;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9e6bee8e/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/CellLifecycleManager.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/CellLifecycleManager.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/CellLifecycleManager.java
deleted file mode 100644
index d30963d..0000000
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/CellLifecycleManager.java
+++ /dev/null
@@ -1,211 +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.component.list.template;
-
-import com.taobao.weex.common.Constants;
-import com.taobao.weex.dom.WXEvent;
-import com.taobao.weex.ui.component.WXComponent;
-import com.taobao.weex.ui.component.WXVContainer;
-import com.taobao.weex.ui.component.list.WXCell;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * cell-slot lifecycle manager, onCreate onAttach onDetach destroy
- * Created by furture on 2017/9/19.
- */
-public class CellLifecycleManager {
-
-    private static final String[] lifecycleEventNames = {
-            Constants.Event.SLOT_LIFECYCLE.CREATE,
-            Constants.Event.SLOT_LIFECYCLE.ATTACH,
-            Constants.Event.SLOT_LIFECYCLE.DETACH,
-            Constants.Event.SLOT_LIFECYCLE.DESTORY
-    };
-
-    private WXRecyclerTemplateList recyclerTemplateList;
-    private Map<String,Map<String,List<String>>> eventSlotWatchRefs;
-
-
-    private Map<Integer,Boolean> firedCreateEvent; // only call once
-
-
-    public CellLifecycleManager(WXRecyclerTemplateList recyclerTemplateList) {
-        this.recyclerTemplateList = recyclerTemplateList;
-        this.eventSlotWatchRefs = new HashMap<>();
-        this.firedCreateEvent = new HashMap<>();
-    }
-
-
-
-    public void filterLifecycleWatchEvent(WXCell cell, WXComponent component){
-        WXEvent wxEvent = component.getDomObject().getEvents();
-        for(String event : lifecycleEventNames){
-            if(wxEvent.contains(event)){
-                Map<String,List<String>> slotWatchRefs = eventSlotWatchRefs.get(event);
-                if(slotWatchRefs == null){
-                    slotWatchRefs = new HashMap<>();
-                    eventSlotWatchRefs.put(event, slotWatchRefs);
-                }
-                List<String> refs =  slotWatchRefs.get(cell.getRef());
-                if(refs == null){
-                    refs = new ArrayList<>(8);
-                    slotWatchRefs.put(cell.getRef(), refs);
-                }
-                if(!refs.contains(component.getRef())){
-                    refs.add(component.getRef());
-                }
-            }
-        }
-        if(component instanceof WXVContainer){
-            WXVContainer container = (WXVContainer) component;
-            for(int i=0; i<container.getChildCount(); i++){
-                WXComponent child = container.getChild(i);
-                filterLifecycleWatchEvent(cell, child);
-            }
-        }
-    }
-
-    /**
-     * onCreate event
-     * */
-    public void onCreate(int position){
-        WXCell  cell = recyclerTemplateList.getSourceTemplate(position);
-        if(cell == null){
-            return;
-        }
-        if(firedCreateEvent.get(position) != null){
-            return;
-        }
-        firedCreateEvent.put(position, true);
-        Map<String,List<String>>  slotWatchCreateRefs = eventSlotWatchRefs.get(Constants.Event.SLOT_LIFECYCLE.CREATE);
-        if(slotWatchCreateRefs == null
-                || slotWatchCreateRefs.get(cell.getRef()) == null
-                || slotWatchCreateRefs.get(cell.getRef()).size() == 0){
-            return;
-        }
-        List<String> refs = slotWatchCreateRefs.get(cell.getRef());
-        if(refs == null || refs.size() == 0){
-            return;
-        }
-        fireChildEvent(Constants.Event.SLOT_LIFECYCLE.CREATE, cell, refs, position);
-    }
-
-    public void onInsert(int position){
-        WXCell  cell = recyclerTemplateList.getSourceTemplate(position);
-        if(cell == null){
-            return;
-        }
-        firedCreateEvent.put(position, true);
-        firedCreateEvent.put(firedCreateEvent.size(), true);
-        Map<String,List<String>>  slotWatchCreateRefs = eventSlotWatchRefs.get(Constants.Event.SLOT_LIFECYCLE.CREATE);
-        if(slotWatchCreateRefs == null
-                || slotWatchCreateRefs.get(cell.getRef()) == null
-                || slotWatchCreateRefs.get(cell.getRef()).size() == 0){
-            return;
-        }
-        List<String> refs = slotWatchCreateRefs.get(cell.getRef());
-        if(refs == null || refs.size() == 0){
-            return;
-        }
-        fireChildEvent(Constants.Event.SLOT_LIFECYCLE.CREATE, cell, refs, position);
-    }
-
-    /**
-     * onAttach event
-     * */
-    public void onAttach(int position, WXCell cell){
-        if(cell == null || position < 0){
-            return;
-        }
-        Map<String,List<String>> slotWatchAttachRefs = eventSlotWatchRefs.get(Constants.Event.SLOT_LIFECYCLE.ATTACH);
-        if(slotWatchAttachRefs == null
-                || slotWatchAttachRefs.get(cell.getRef()) == null
-                || slotWatchAttachRefs.get(cell.getRef()).size() == 0){
-            return;
-        }
-        List<String> refs = slotWatchAttachRefs.get(cell.getRef());
-        fireChildEvent(Constants.Event.SLOT_LIFECYCLE.ATTACH, cell, refs, position);
-    }
-
-    /**
-     * onDetach event
-     * */
-    public void onDetach(int position, WXCell cell){
-        if(cell == null || position < 0){
-            return;
-        }
-        Map<String,List<String>> slotWatchDetachRefs = eventSlotWatchRefs.get(Constants.Event.SLOT_LIFECYCLE.ATTACH);
-        if(slotWatchDetachRefs == null
-                || slotWatchDetachRefs.get(cell.getRef()) == null
-                || slotWatchDetachRefs.get(cell.getRef()).size() == 0){
-            return;
-        }
-        List<String> refs = slotWatchDetachRefs.get(cell.getRef());
-        fireChildEvent(Constants.Event.SLOT_LIFECYCLE.DETACH, cell, refs, position);
-    }
-
-    /**
-     * onDestory event
-     * */
-    public void onDestory(int position){
-        Boolean hasCreated = firedCreateEvent.remove(position);
-        if(hasCreated == null){
-            return;
-        }
-        Map<String,List<String>> slotWatchDestroyRefs = eventSlotWatchRefs.get(Constants.Event.SLOT_LIFECYCLE.DESTORY);
-        if(slotWatchDestroyRefs == null
-                || slotWatchDestroyRefs.size() == 0){
-            return;
-        }
-        WXCell cell = recyclerTemplateList.getSourceTemplate(position);
-        if(cell == null){
-            return;
-        }
-        List<String> refs = slotWatchDestroyRefs.get(cell.getRef());
-        if(refs == null || refs.size() == 0){
-            return;
-        }
-        fireChildEvent(Constants.Event.SLOT_LIFECYCLE.DESTORY, cell, refs, position);
-    }
-
-    public Map<Integer, Boolean> getFiredCreateEvent() {
-        return firedCreateEvent;
-    }
-
-    private final  void  fireChildEvent(String event, WXCell cell, List<String> refs, int position){
-        if(refs == null || refs.size() == 0){
-            return;
-        }
-        for(String ref : refs){
-            List<WXComponent> components = recyclerTemplateList.findChildListByRef(cell, ref);
-            if(components == null || components.size() == 0){
-                continue;
-            }
-            for(WXComponent component : components) {
-                Map<String, Object> params = new HashMap<>(8);
-                params.put("index", position);
-                component.fireEvent(event, params);
-            }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9e6bee8e/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/DomTreeBuilder.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/DomTreeBuilder.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/DomTreeBuilder.java
new file mode 100644
index 0000000..c475195
--- /dev/null
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/DomTreeBuilder.java
@@ -0,0 +1,83 @@
+/**
+ * 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;
+
+import com.taobao.weex.WXSDKManager;
+import com.taobao.weex.dom.DOMActionContext;
+import com.taobao.weex.dom.WXDomObject;
+import com.taobao.weex.dom.action.TraceableAction;
+import com.taobao.weex.ui.component.WXComponent;
+import com.taobao.weex.ui.component.WXComponentFactory;
+import com.taobao.weex.ui.component.WXVContainer;
+
+/**
+ * Created by furture on 2017/10/2.
+ */
+
+class DomTreeBuilder extends TraceableAction {
+
+
+
+
+    public WXComponent generateComponentTree(DOMActionContext context, WXDomObject dom, WXVContainer parent) {
+        if (dom == null) {
+            return null;
+        }
+       long startNanos = System.nanoTime();
+        WXComponent component = WXComponentFactory.newInstance(context.getInstance(), dom, parent);
+        if (component != null) {
+            component.mTraceInfo.domThreadStart = dom.mDomThreadTimestamp;
+            component.mTraceInfo.rootEventId = mTracingEventId;
+            component.mTraceInfo.domQueueTime = mDomQueueTime;
+        }
+        ((WXDomObject)component.getDomObject()).applyStyleToNode();
+        context.registerDOMObject(dom.getRef(), dom);
+        context.registerComponent(dom.getRef(), component);
+        if (component instanceof WXVContainer) {
+            WXVContainer container = (WXVContainer) component;
+            WXDomObject parentDom = (WXDomObject) container.getDomObject();
+            int count = dom.childCount();
+            WXDomObject child = null;
+            for (int i = 0; i < count; ++i) {
+                child = dom.getChild(i);
+                if (child != null) {
+                    WXComponent childComponent = generateComponentTree(context, child, container);
+                    container.addChild(childComponent);
+                    parentDom.add((WXDomObject) childComponent.getDomObject(), -1);
+                }
+            }
+        }
+        if (component != null) {
+            component.mTraceInfo.domThreadNanos = System.nanoTime() - startNanos;
+        }
+        return component;
+    }
+
+    public static final WXComponent buildTree(WXDomObject domObject, WXVContainer parent){
+        DOMActionContext domActionContext = WXSDKManager.getInstance().getWXDomManager().getDomContext(parent.getInstanceId());
+        if(domActionContext == null){
+            return null;
+        }
+        domObject.getStyles().put("display", "flex");
+        DomTreeBuilder builder = new DomTreeBuilder();
+        return builder.generateComponentTree(domActionContext, domObject, parent);
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9e6bee8e/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/TemplateCache.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/TemplateCache.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/TemplateCache.java
new file mode 100644
index 0000000..eab80bc
--- /dev/null
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/TemplateCache.java
@@ -0,0 +1,30 @@
+/**
+ * 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;
+import com.taobao.weex.ui.component.list.WXCell;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+/**
+ * preload cell cache
+ * Created by furture on 2017/9/29.
+ */
+class TemplateCache {
+    ConcurrentLinkedQueue<WXCell> cells = new ConcurrentLinkedQueue<>();
+    boolean isLoadIng = false;
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9e6bee8e/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/TemplateViewHolder.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/TemplateViewHolder.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/TemplateViewHolder.java
index a418e3e..d0b5dbf 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/TemplateViewHolder.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/TemplateViewHolder.java
@@ -47,6 +47,8 @@ public class TemplateViewHolder extends ListBaseViewHolder {
 
     public AsyncTask<Void, Void, Void> asyncTask;
 
+    public Object  data;
+
     /**
      * header position
      * */

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9e6bee8e/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 5d23bf6..d371ab2 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
@@ -25,6 +25,7 @@ import android.graphics.PointF;
 import android.os.AsyncTask;
 import android.os.Build;
 import android.os.Looper;
+import android.os.MessageQueue;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.v4.util.ArrayMap;
@@ -43,14 +44,16 @@ 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.bridge.WXBridgeManager;
 import com.taobao.weex.common.Constants;
 import com.taobao.weex.common.ICheckBindingScroller;
 import com.taobao.weex.common.OnWXScrollListener;
-import com.taobao.weex.dom.ImmutableDomObject;
 import com.taobao.weex.dom.WXAttr;
 import com.taobao.weex.dom.WXCellDomObject;
+import com.taobao.weex.dom.WXDomHandler;
 import com.taobao.weex.dom.WXDomObject;
 import com.taobao.weex.dom.WXEvent;
 import com.taobao.weex.dom.WXRecyclerDomObject;
@@ -81,10 +84,12 @@ import com.taobao.weex.utils.WXViewUtils;
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentLinkedQueue;
 
 import static com.taobao.weex.common.Constants.Name.LOADMOREOFFSET;
 
@@ -96,10 +101,11 @@ import static com.taobao.weex.common.Constants.Name.LOADMOREOFFSET;
 @Component(lazyload = false)
 public class WXRecyclerTemplateList extends WXVContainer<BounceRecyclerView> implements
         IRecyclerAdapterListener<TemplateViewHolder>, IOnLoadMoreListener, Scrollable {
-    private static final String TAG = "WXRecyclerTemplateList";
+    public static final String TAG = "WXRecyclerTemplateList";
 
     private static final String NAME_HAS_FIXED_SIZE = "hasFixedSize";
     private static final String NAME_ITEM_VIEW_CACHE_SIZE = "itemViewCacheSize";
+    private static final String NAME_TEMPLATE_CACHE_SIZE = "templateCacheSize";
 
 
     private WXRecyclerDomObject mDomObject;
@@ -135,11 +141,12 @@ public class WXRecyclerTemplateList extends WXVContainer<BounceRecyclerView> imp
 
 
 
-    private Map<String, WXCell> mTemplates;
+    private Map<String, WXCell> mTemplateSources;
     private String  listDataTemplateKey = Constants.Name.Recycler.SLOT_TEMPLATE_TYPE;
     private Runnable listUpdateRunnable;
-    private ConcurrentHashMap<String, WXCell> mTemplatesCache;
-    private ConcurrentHashMap<String, Boolean> mTemplateRendered;
+    private ConcurrentHashMap<String, TemplateCache> mTemplatesCache;
+    private int templateCacheSize = 2;
+
 
     /**
      * sticky helper
@@ -148,12 +155,6 @@ public class WXRecyclerTemplateList extends WXVContainer<BounceRecyclerView> imp
 
 
     /**
-     * cell item lifecycle manager
-     * */
-    private  CellLifecycleManager cellLifecycleManager;
-
-
-    /**
      * appear and disappear event managaer
      * */
     private ArrayMap<Integer, List<AppearanceHelper>> mAppearHelpers = new ArrayMap<>();
@@ -166,6 +167,9 @@ public class WXRecyclerTemplateList extends WXVContainer<BounceRecyclerView> imp
      * */
     private ArrayMap<Integer, Map<String,Map<Integer, List<Object>>>> mDisAppearWatchList = new ArrayMap<>();
 
+    private ArrayStack bindIngStackContext = new ArrayStack();
+    private Map bindIngMapContext = new HashMap();
+
     public WXRecyclerTemplateList(WXSDKInstance instance, WXDomObject node, WXVContainer parent) {
         super(instance, node, parent);
         initRecyclerTemplateList(instance, node, parent);
@@ -180,10 +184,9 @@ public class WXRecyclerTemplateList extends WXVContainer<BounceRecyclerView> imp
         }
         mTemplateViewTypes = new ArrayMap<>();
         mTemplateViewTypes.put("", 0); //empty view, when template was not sended
-        mTemplates = new HashMap<>();
+        mTemplateSources = new HashMap<>();
         mTemplatesCache = new ConcurrentHashMap<>();
         mStickyHelper = new TemplateStickyHelper(this);
-        cellLifecycleManager = new CellLifecycleManager(this);
         orientation = mDomObject.getOrientation();
         listDataTemplateKey = WXUtils.getString(getDomObject().getAttrs().get(Constants.Name.Recycler.LIST_DATA_TEMPLATE_KEY), Constants.Name.Recycler.SLOT_TEMPLATE_TYPE);
         listDataItemKey = WXUtils.getString(getDomObject().getAttrs().get(Constants.Name.Recycler.LIST_DATA_ITEM), listDataItemKey);
@@ -194,7 +197,12 @@ public class WXRecyclerTemplateList extends WXVContainer<BounceRecyclerView> imp
                 listData = array;
             }
         }
-        mTemplateRendered = new ConcurrentHashMap<>();
+
+        if(mDomObject != null && mDomObject.getCellList() != null){
+            for(int i=0; i<mDomObject.getCellList().size(); i++){
+                addChild(DomTreeBuilder.buildTree(mDomObject.getCellList().get(i),  this));
+            }
+        }
     }
 
     @Override
@@ -206,8 +214,13 @@ public class WXRecyclerTemplateList extends WXVContainer<BounceRecyclerView> imp
             bounceRecyclerView.getInnerView().addItemDecoration(RecyclerTransform.parseTransforms(getOrientation(), transforms));
         }
         mItemAnimator = bounceRecyclerView.getInnerView().getItemAnimator();
+
+        if(attrs.get(NAME_TEMPLATE_CACHE_SIZE) != null){
+            templateCacheSize =  WXUtils.getInteger(attrs.get(NAME_TEMPLATE_CACHE_SIZE), templateCacheSize);
+        }
+
         boolean hasFixedSize = false;
-        int itemViewCacheSize = 4;
+        int itemViewCacheSize = 2;
         if(attrs.get(NAME_ITEM_VIEW_CACHE_SIZE) != null){
             itemViewCacheSize = WXUtils.getNumberInt(getDomObject().getAttrs().get(NAME_ITEM_VIEW_CACHE_SIZE), itemViewCacheSize);
         }
@@ -217,7 +230,9 @@ public class WXRecyclerTemplateList extends WXVContainer<BounceRecyclerView> imp
         RecyclerViewBaseAdapter recyclerViewBaseAdapter = new RecyclerViewBaseAdapter<>(this);
         recyclerViewBaseAdapter.setHasStableIds(true);
         bounceRecyclerView.getInnerView().setItemAnimator(null);
-        bounceRecyclerView.getInnerView().setItemViewCacheSize(itemViewCacheSize);
+        if(itemViewCacheSize != 2) {
+            bounceRecyclerView.getInnerView().setItemViewCacheSize(itemViewCacheSize);
+        }
         bounceRecyclerView.getInnerView().setHasFixedSize(hasFixedSize);
         bounceRecyclerView.setRecyclerViewBaseAdapter(recyclerViewBaseAdapter);
         bounceRecyclerView.setOverScrollMode(View.OVER_SCROLL_NEVER);
@@ -302,6 +317,9 @@ public class WXRecyclerTemplateList extends WXVContainer<BounceRecyclerView> imp
                 if(getHostView() != null && getHostView().getRecyclerViewBaseAdapter() != null){
                     getHostView().getRecyclerViewBaseAdapter().notifyDataSetChanged();
                 }
+                if(WXEnvironment.isApkDebugable()){
+                    WXLogUtils.d(TAG, "WXTemplateList notifyDataSetChanged");
+                }
             }
         };
         return bounceRecyclerView;
@@ -537,7 +555,9 @@ public class WXRecyclerTemplateList extends WXVContainer<BounceRecyclerView> imp
 
     @Override
     public void addChild(WXComponent child, int index) {
-        super.addChild(child, index);
+        if(!(child instanceof  WXCell)) {
+            super.addChild(child, index);
+        }
         if(child instanceof  WXBaseRefresh){
             return;
         }
@@ -546,19 +566,18 @@ public class WXRecyclerTemplateList extends WXVContainer<BounceRecyclerView> imp
                 Object templateId = child.getDomObject().getAttrs().get(Constants.Name.Recycler.SLOT_TEMPLATE_TYPE);
                 String key = WXUtils.getString(templateId, null);
                 if(key != null){
-                    //set visible false, skip layout in dom thread, set visible true in onCreateViewHolder
-                    if(child.getDomObject() != null) {
-                        WXDomObject domObject = (WXDomObject) child.getDomObject();
-                        domObject.setVisible(false);
+                    if(child.getDomObject() instanceof  WXCellDomObject
+                            && getDomObject() instanceof  WXRecyclerDomObject){
+                        WXCellDomObject domObject = (WXCellDomObject) child.getDomObject();
+                        domObject.setRecyclerDomObject((WXRecyclerDomObject) getDomObject());
                     }
-                    mTemplates.put(key, (WXCell) child);
-                    asyncPreloadCellCopyCache(key);
+                    mTemplateSources.put(key, (WXCell) child);
+                    ensureSourceCellRenderWithData((WXCell)child);
                     if(mTemplateViewTypes.get(key) == null){
                         mTemplateViewTypes.put(key, mTemplateViewTypes.size());
                     }
                 }
             }
-            cellLifecycleManager.filterLifecycleWatchEvent((WXCell)child, child);
             notifyUpdateList();
         }
     }
@@ -602,21 +621,6 @@ public class WXRecyclerTemplateList extends WXVContainer<BounceRecyclerView> imp
     }
 
 
-    /**
-     * To determine whether an animation is needed
-     * @param child
-     * @return
-     */
-    private boolean isRemoveAnimation(WXComponent child) {
-        ImmutableDomObject domObject = child.getDomObject();
-        if (domObject != null) {
-            Object attr = domObject.getAttrs().get(Constants.Name.DELETE_CELL_ANIMATION);
-            if (Constants.Value.DEFAULT.equals(attr)) {
-                return true;
-            }
-        }
-        return false;
-    }
 
     @Override
     public void computeVisiblePointInViewCoordinate(PointF pointF) {
@@ -727,23 +731,13 @@ public class WXRecyclerTemplateList extends WXVContainer<BounceRecyclerView> imp
 
     @JSMethod
     public void setListData(Object param){
-        if(listData != null){
-            for(int i=0;i<listData.size(); i++){
-                cellLifecycleManager.onDestory(i);
-            }
-        }
-        boolean update = listData != null;
+        boolean update = listData != null &&  listData != param;
         if(param instanceof  JSONArray){
             listData = (JSONArray) param;
         }
         if(update){
             notifyUpdateList();
         }
-        if(listData != null){
-            for(int i=0; i<listData.size(); i++){
-                cellLifecycleManager.onCreate(i);
-            }
-        }
     }
 
     @JSMethod
@@ -751,14 +745,9 @@ public class WXRecyclerTemplateList extends WXVContainer<BounceRecyclerView> imp
         if(listData == null){
             listData = new JSONArray();
         }
-        int position = listData.size();
         if(arrayObject instanceof  JSONArray){
             listData.addAll(arrayObject);
         }
-        int end = listData.size();
-        for(int i=position; i<end; i++){
-            cellLifecycleManager.onCreate(position);
-        }
         notifyUpdateList();
     }
 
@@ -771,7 +760,6 @@ public class WXRecyclerTemplateList extends WXVContainer<BounceRecyclerView> imp
             return;
         }
         listData.add(index, data);
-        cellLifecycleManager.onInsert(index);
         notifyUpdateList();
     }
 
@@ -783,13 +771,7 @@ public class WXRecyclerTemplateList extends WXVContainer<BounceRecyclerView> imp
         if(listData == null || index >= listData.size()){
             return;
         }
-        int before = getItemViewType(index);
         listData.set(index, data);
-        int after = getItemViewType(index);
-        if(before != after){
-            cellLifecycleManager.onDestory(index);
-            cellLifecycleManager.onCreate(index);
-        }
         notifyUpdateList();
     }
 
@@ -806,15 +788,7 @@ public class WXRecyclerTemplateList extends WXVContainer<BounceRecyclerView> imp
             }
             index -= offset;
             if(index < listData.size()){
-                int markPostion = listData.size() - 1;
-                cellLifecycleManager.onDestory(index);
                 listData.remove((int)index);
-                if(index < listData.size()){
-                    cellLifecycleManager.getFiredCreateEvent().put(index, true);
-                }
-                if(markPostion >= 0){
-                    cellLifecycleManager.getFiredCreateEvent().remove(markPostion);
-                }
                 offset++;
             }
         }
@@ -1002,8 +976,8 @@ public class WXRecyclerTemplateList extends WXVContainer<BounceRecyclerView> imp
         if(mTemplateViewTypes != null){
             mTemplateViewTypes.clear();
         }
-        if(mTemplates != null){
-            mTemplates.clear();
+        if(mTemplateSources != null){
+            mTemplateSources.clear();
         }
         if(mAppearHelpers != null){
             mAppearHelpers.clear();
@@ -1017,8 +991,7 @@ public class WXRecyclerTemplateList extends WXVContainer<BounceRecyclerView> imp
 
 
     @Override
-    public void onViewRecycled(TemplateViewHolder holder) {
-    }
+    public void onViewRecycled(TemplateViewHolder holder) {}
 
     @Override
     public void onBindViewHolder(final TemplateViewHolder templateViewHolder, int position) {
@@ -1029,110 +1002,96 @@ public class WXRecyclerTemplateList extends WXVContainer<BounceRecyclerView> imp
         if(component == null){
             return;
         }
-        cellLifecycleManager.onDetach(templateViewHolder.getHolderPosition(), component);
         long start = System.currentTimeMillis();
+        boolean async = templateViewHolder.getHolderPosition() >= 0;
         templateViewHolder.setHolderPosition(position);
-        Statements.doRender(component, getStackContextForPosition(position));
-        if(WXEnvironment.isApkDebugable()){
-            WXLogUtils.d(TAG, position + getTemplateKey(position) + " onBindViewHolder render used " + (System.currentTimeMillis() - start));
-        }
-        Layouts.doLayoutAsync(templateViewHolder);
-        cellLifecycleManager.onAttach(position, component);
-        if(WXEnvironment.isApkDebugable()){
-            WXLogUtils.d(TAG,  position + getTemplateKey(position) + " onBindViewHolder layout used " + (System.currentTimeMillis() - start));
+        Object data = listData.get(position);
+        if(component.getRenderData() == data){
+            if(!async){
+                if(!component.isHasLayout()) {
+                    Layouts.doLayoutAsync(templateViewHolder, async);
+                }
+                if(WXEnvironment.isApkDebugable()){
+                    WXLogUtils.d(TAG,  position + getTemplateKey(position) + " onBindViewHolder source layout used " + (System.currentTimeMillis() - start) + async);
+                }
+            }
+            component.setHasLayout(true);
+        }else{
+            List<WXComponent> updates = Statements.doRender(component, getStackContextForPosition(position, data));
+            Statements.doInitCompontent(updates);
+            component.setRenderData(data);
+            if(WXEnvironment.isApkDebugable()){
+                WXLogUtils.d(TAG, position + getTemplateKey(position) + " onBindViewHolder render used " + (System.currentTimeMillis() - start));
+            }
+            if(component.isHasLayout()){
+                async = true;
+            }
+            Layouts.doLayoutAsync(templateViewHolder, async);
+            component.setHasLayout(true);
+            if(WXEnvironment.isApkDebugable()){
+                WXLogUtils.d(TAG,  position + getTemplateKey(position) + " onBindViewHolder layout used " + (System.currentTimeMillis() - start) + async);
+            }
         }
     }
 
     @Override
     public TemplateViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
         String template = mTemplateViewTypes.keyAt(viewType);
-        WXCell source = mTemplates.get(template);
+        WXCell source = mTemplateSources.get(template);
         if(source == null){
             FrameLayout view = new FrameLayout(getContext());
             view.setLayoutParams(new FrameLayout.LayoutParams(0, 0));
             return new TemplateViewHolder(view, viewType);
         }
-        long start = System.currentTimeMillis();
-        WXCell component = mTemplatesCache.remove(template);
-        boolean needLayout = false;
-        if(component == null) {
-            component = (WXCell) copyCell(source);
-            needLayout = true;
+        TemplateCache cache = mTemplatesCache.get(template);
+        WXCell component =  null;
+        boolean cacheHit = true;
+        if(cache != null && cache.cells != null && cache.cells.size() > 0){
+            component = cache.cells.poll();
         }
-        asyncPreloadCellCopyCache(template);
-        CSSLayoutContext layoutContext = null;
-        if(needLayout){
-            layoutContext = new CSSLayoutContext();
-            Layouts.doSafeLayout(component, layoutContext);
-            if(WXEnvironment.isApkDebugable()){
-                WXLogUtils.d(TAG, template + " onCreateViewHolder sync layout used " + (System.currentTimeMillis() - start));
-            }
+        if(cache == null ||  !cache.isLoadIng){
+            asyncLoadTemplateCache(template);
         }
-        Layouts.setLayout(component, false);
-        component.lazy(false);
-        component.createView();
-        if(WXEnvironment.isApkDebugable()){
-            WXLogUtils.d(TAG, template + " onCreateViewHolder view used " + (System.currentTimeMillis() - start));
+        if(component == null){
+            cacheHit = false;
+            if(!source.isSourceUsed()){
+                source.setSourceUsed(true);
+                ensureSourceCellRenderWithData(source);
+                component = source;
+                if(WXEnvironment.isApkDebugable()) {
+                    WXLogUtils.d(TAG, template + " onCreateViewHolder source");
+                }
+            }
         }
-        component.applyLayoutAndEvent(component);
-        if(WXEnvironment.isApkDebugable()) {
-            WXLogUtils.d(TAG, template +  " onCreateViewHolder apply layout used " + (System.currentTimeMillis() - start));
+        if(component == null) {
+            long start = System.currentTimeMillis();
+            component = (WXCell) copyCell(source);
+            if(WXEnvironment.isApkDebugable()) {
+                WXLogUtils.d(TAG, template + " onCreateViewHolder copy used " + (System.currentTimeMillis() - start));
+            }
         }
-        component.bindData(component);
-        if(WXEnvironment.isApkDebugable()) {
-            WXLogUtils.d(TAG, template + " onCreateViewHolder bindData used " + (System.currentTimeMillis() - start));
+        if(component.isLazy()) {
+            doInitLazyCell(component, template, false);
+            if(WXEnvironment.isApkDebugable()) {
+                WXLogUtils.d(TAG, template + " onCreateViewHolder  cache hit " + cacheHit   + " idle init false ");
+            }
+        }else{
+            if(WXEnvironment.isApkDebugable()) {
+                WXLogUtils.d(TAG, template + " onCreateViewHolder  cache hit " + cacheHit + " idle init true");
+            }
         }
         TemplateViewHolder templateViewHolder = new TemplateViewHolder(component, viewType);
-        templateViewHolder.setLayoutContext(layoutContext);
         return  templateViewHolder;
     }
 
-    private void asyncPreloadCellCopyCache(final String template) {
-        final WXCell cell = mTemplates.get(template);
-        if(cell == null){
-            return;
-        }
-        if(mTemplatesCache.get(template) != null){
-            return;
-        }
-        AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
-            @Override
-            public void run() {
-                if(cell.getInstance() == null || cell.getInstance().isDestroy()){
-                    return;
-                }
-                WXCell component = (WXCell) copyCell(cell);
-                if(cell.getInstance() == null || cell.getInstance().isDestroy()){
-                    return;
-                }
-                Layouts.doSafeLayout(component, new CSSLayoutContext());
-                mTemplatesCache.put(template, component);
-            }
-        });
-    }
 
     /**
-     * copy cell component from source, and return source
+     * copy cell component from source, init render data, and return source
+     * if none data, return null
      * */
-    private WXComponent copyCell(WXComponent  cell){
-        /** pre render for cell */
-        Boolean rendered = mTemplateRendered.get(cell.getRef());
-        if(rendered == null || !rendered) {
-            if(listData != null){
-                for(int i=0; i<listData.size(); i++){
-                    WXCell source = getSourceTemplate(i);
-                    if(source == cell){
-                        Statements.doRender(cell, getStackContextForPosition(i));
-                        mTemplateRendered.put(source.getRef(), true);
-                        break;
-                    }
-                }
-            }
-        }
+    private WXComponent copyCell(WXCell cell){
+        ensureSourceCellRenderWithData(cell);
         WXCell component = (WXCell) Statements.copyComponentTree(cell);
-        if(component.getDomObject() != null){
-            ((WXDomObject)component.getDomObject()).setVisible(true);
-        }
         if(component.getDomObject() instanceof  WXCellDomObject
                 && getDomObject() instanceof  WXRecyclerDomObject){
             WXCellDomObject domObject = (WXCellDomObject) component.getDomObject();
@@ -1141,6 +1100,26 @@ public class WXRecyclerTemplateList extends WXVContainer<BounceRecyclerView> imp
         return component;
     }
 
+    private void ensureSourceCellRenderWithData(WXCell cell){
+        if(cell.getRenderData() == null){
+            if(listData != null && listData.size() > 0){
+                synchronized (this){
+                    if(cell.getRenderData() == null){
+                        for(int i=0; i<listData.size(); i++){
+                            if(cell == getSourceTemplate(i)){
+                                Object data = listData.get(i);
+                                Statements.doRender(cell, getStackContextForPosition(i, data));
+                                cell.setRenderData(data);
+                                //WXSDKManager.getInstance().getWXDomManager().postAction(getInstanceId(), new RenderSourceCellAction(cell, null, data), false);
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
     /**
      * @param position
      * when template not send, return an invalid id, use empty view holder.
@@ -1164,14 +1143,19 @@ public class WXRecyclerTemplateList extends WXVContainer<BounceRecyclerView> imp
     /**
      * return code context for render component
      * */
-    private ArrayStack getStackContextForPosition(int position){
-        ArrayStack stack = new ArrayStack();
-        Map map = new HashMap();
+    private ArrayStack getStackContextForPosition(int position,  Object item){
+        if(!bindIngStackContext.isEmpty()){
+            bindIngStackContext.getList().clear();
+        }
+        if(!bindIngMapContext.isEmpty()){
+            bindIngMapContext.clear();
+        }
+        ArrayStack stack = bindIngStackContext;
+        Map map = bindIngMapContext;
         if(listData != null){
             stack.push(listData);
             stack.push(map);
             map.put(listDataKey, listData);
-            Object item = listData.get(position);
             if(!TextUtils.isEmpty(listDataIndexKey)) {
                 map.put(listDataIndexKey, position);
             }
@@ -1201,7 +1185,7 @@ public class WXRecyclerTemplateList extends WXVContainer<BounceRecyclerView> imp
      * */
     public WXCell getSourceTemplate(int position){
         String template = getTemplateKey(position);
-        return mTemplates.get(template);
+        return mTemplateSources.get(template);
     }
 
 
@@ -1236,7 +1220,7 @@ public class WXRecyclerTemplateList extends WXVContainer<BounceRecyclerView> imp
         if(mTemplateViewTypes == null || mTemplateViewTypes.size() <= 1){
             return 0;
         }
-        if(mTemplates == null || mTemplates.size() == 0){
+        if(mTemplateSources == null || mTemplateSources.size() == 0){
             return  0;
         }
         return listData.size();
@@ -1385,7 +1369,7 @@ public class WXRecyclerTemplateList extends WXVContainer<BounceRecyclerView> imp
             if(map == null){
                 continue;
             }
-            WXCell template = mTemplates.get(getTemplateKey(position));
+            WXCell template = mTemplateSources.get(getTemplateKey(position));
             if(template == null){
                 return;
             }
@@ -1420,15 +1404,16 @@ public class WXRecyclerTemplateList extends WXVContainer<BounceRecyclerView> imp
     }
 
     private void  notifyUpdateList(){
-        if(getHostView() != null
-                && listUpdateRunnable != null
-                && getHostView().getInnerView() != null){
-            if(Looper.getMainLooper().getThread().getId() != Thread.currentThread().getId()){
-                getHostView().removeCallbacks(listUpdateRunnable);
-                getHostView().post(listUpdateRunnable);
-            }else{
-                listUpdateRunnable.run();
-            }
+        if(getHostView() == null
+                || getHostView().getInnerView() == null
+                || listUpdateRunnable == null){
+            return;
+        }
+        if(Looper.getMainLooper().getThread().getId() != Thread.currentThread().getId()){
+            getHostView().removeCallbacks(listUpdateRunnable);
+            getHostView().post(listUpdateRunnable);
+        }else{
+            listUpdateRunnable.run();
         }
     }
 
@@ -1545,4 +1530,126 @@ public class WXRecyclerTemplateList extends WXVContainer<BounceRecyclerView> imp
         }
         return  componentList;
     }
+
+
+    /**
+     * copy cell async and save to cache
+     * */
+    private void asyncLoadTemplateCache(final String template) {
+        if(Thread.currentThread() != Looper.getMainLooper().getThread()){
+            if(listData == null || listData.size() == 0){
+                return;
+            }
+            boolean firstScreenContains = false;
+            for(int i=0; i<listData.size(); i++){
+                if(template.equals(getTemplateKey(i))){
+                    firstScreenContains = true;
+                    break;
+                }
+            }
+            if(!firstScreenContains){
+                return;
+            }
+        }
+        final WXCell source = mTemplateSources.get(template);
+        if(source == null){
+            return;
+        }
+        TemplateCache cellCache = mTemplatesCache.get(template);
+        if(cellCache == null){
+            cellCache = new TemplateCache();
+            mTemplatesCache.put(template, cellCache);
+        }
+        if(cellCache.cells.size() >= templateCacheSize){
+            cellCache.isLoadIng = false;
+            return;
+        }
+        if(cellCache.isLoadIng){
+            return;
+        }
+        cellCache.isLoadIng = true;
+        AsyncTask<Void,Void, Void> preloadTask = new AsyncTask<Void, Void, Void>() {
+            @Override
+            protected Void doInBackground(Void... params) {
+                try {
+                    Thread.sleep(100);
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+                TemplateCache cellCache = mTemplatesCache.get(template);
+                if(cellCache == null || cellCache.cells == null){
+                    return null;
+                }
+                while (cellCache.cells.size() < templateCacheSize){
+                    WXCell component = (WXCell) copyCell(source);
+                    if(component == null){
+                        return null;
+                    }
+                    if(source.getInstance() == null || source.getInstance().isDestroy()){
+                        return null;
+                    }
+                    cellCache.cells.add(component);
+                }
+                return null;
+            }
+            @Override
+            protected void onPostExecute(Void aVoid) {
+                if(source.getInstance() == null || source.getInstance().isDestroy()){
+                    return;
+                }
+                final TemplateCache cellCache = mTemplatesCache.get(template);
+                if(cellCache == null){
+                    return;
+                }
+                if(cellCache.cells == null
+                        || cellCache.cells.size() == 0){
+                    cellCache.isLoadIng = false;
+                    return;
+                }
+                Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {
+                    @Override
+                    public boolean queueIdle() {
+                        if(source.getInstance() == null || source.getInstance().isDestroy()){
+                            return false;
+                        }
+                        ConcurrentLinkedQueue<WXCell> queue =  cellCache.cells;
+                        Iterator<WXCell> iterator =  queue.iterator();
+                        while (iterator.hasNext()){
+                            WXCell  component =  iterator.next();
+                            if(component.isLazy()){
+                                doInitLazyCell(component, template, true);
+                                return iterator.hasNext();
+                            }
+                            if(!component.isHasLayout()){
+                                Layouts.doSafeLayout(component, new CSSLayoutContext());
+                                component.setHasLayout(true);
+                            }
+                        }
+                        return false;
+                    }
+                });
+                cellCache.isLoadIng = false;
+            }
+        };
+        preloadTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+    }
+
+    private static void  doInitLazyCell(WXCell component, String template, boolean inPreload){
+        if(component.isLazy()){
+            long start = System.currentTimeMillis();
+            component.lazy(false);
+            component.createView();
+            if(WXEnvironment.isApkDebugable()) {
+                WXLogUtils.d(TAG,  "doInitLazyCell " + inPreload + template +  " createView used " + (System.currentTimeMillis() - start));
+            }
+            component.applyLayoutAndEvent(component);
+            if(WXEnvironment.isApkDebugable()) {
+                WXLogUtils.d(TAG,  "doInitLazyCell " + inPreload  + template +  " apply layout used " + (System.currentTimeMillis() - start));
+            }
+            component.bindData(component);
+            if(WXEnvironment.isApkDebugable()) {
+                WXLogUtils.d(TAG, "doInitLazyCell " + inPreload + template + " bindData used " + (System.currentTimeMillis() - start));
+            }
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9e6bee8e/android/sdk/src/test/java/com/taobao/weex/ui/component/binding/StatementTest.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/test/java/com/taobao/weex/ui/component/binding/StatementTest.java b/android/sdk/src/test/java/com/taobao/weex/ui/component/binding/StatementTest.java
index 3566816..3924a3a 100644
--- a/android/sdk/src/test/java/com/taobao/weex/ui/component/binding/StatementTest.java
+++ b/android/sdk/src/test/java/com/taobao/weex/ui/component/binding/StatementTest.java
@@ -76,7 +76,7 @@ public class StatementTest {
     public void testVFor() throws Exception {
         WXCell cell = createVForNode();
         int count = 3;
-        Statements.doRenderComponent(cell, createContext(count));
+        Statements.doRender(cell, createContext(count));
         Assert.assertTrue(cell.getChildCount() == 1);
         WXDiv div = (WXDiv) cell.getChild(0);
         Assert.assertEquals(div.getChildCount(), count);
@@ -88,7 +88,7 @@ public class StatementTest {
         WXComponent childThree = div.getChild(2);
 
         count = 4;
-        Statements.doRenderComponent(cell, createContext(count));
+        Statements.doRender(cell, createContext(count));
         Assert.assertTrue(cell.getChildCount() == 1);
         div = (WXDiv) cell.getChild(0);
         Assert.assertTrue(div.getChildCount() == count);
@@ -98,7 +98,7 @@ public class StatementTest {
         WXComponent childFour = div.getChild(3);
 
         count = 5;
-        Statements.doRenderComponent(cell, createContext(count));
+        Statements.doRender(cell, createContext(count));
         Assert.assertTrue(cell.getChildCount() == 1);
         div = (WXDiv) cell.getChild(0);
         Assert.assertTrue(div.getChildCount() == count);
@@ -109,7 +109,7 @@ public class StatementTest {
 
 
         count = 3;
-        Statements.doRenderComponent(cell, createContext(count));
+        Statements.doRender(cell, createContext(count));
         Assert.assertTrue(cell.getChildCount() == 1);
         div = (WXDiv) cell.getChild(0);
         Assert.assertTrue(div.getChildCount() == 5);