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/10 04:03:01 UTC
[6/6] 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/6849d52f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-weex/tree/6849d52f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-weex/diff/6849d52f
Branch: refs/heads/release-0.16
Commit: 6849d52f5331ed9b16b94cd03c2bf927b28af213
Parents: 7cc450d
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:02:29 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/6849d52f/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/6849d52f/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/6849d52f/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/6849d52f/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/6849d52f/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/6849d52f/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/6849d52f/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/6849d52f/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/6849d52f/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/6849d52f/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/6849d52f/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/6849d52f/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/6849d52f/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/6849d52f/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/6849d52f/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/6849d52f/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/6849d52f/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/6849d52f/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/6849d52f/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/6849d52f/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);