diff --git a/doric/src/main/java/pub/doric/shader/SuperNode.java b/doric/src/main/java/pub/doric/shader/SuperNode.java index bf8ed08c..b03d55aa 100644 --- a/doric/src/main/java/pub/doric/shader/SuperNode.java +++ b/doric/src/main/java/pub/doric/shader/SuperNode.java @@ -85,6 +85,10 @@ public abstract class SuperNode extends ViewNode { subNodes.clear(); } + public void removeSubModel(String id) { + subNodes.remove(id); + } + protected abstract void blendSubNode(JSObject subProperties); protected void blendSubLayoutConfig(ViewNode viewNode, JSObject jsObject) { diff --git a/doric/src/main/java/pub/doric/shader/TextNode.java b/doric/src/main/java/pub/doric/shader/TextNode.java index 87c5faea..a8de13c2 100644 --- a/doric/src/main/java/pub/doric/shader/TextNode.java +++ b/doric/src/main/java/pub/doric/shader/TextNode.java @@ -39,6 +39,7 @@ public class TextNode extends ViewNode { protected TextView build() { TextView tv = new TextView(getContext()); tv.setGravity(Gravity.CENTER); + tv.setMaxLines(1); return tv; } diff --git a/doric/src/main/java/pub/doric/shader/list/ListAdapter.java b/doric/src/main/java/pub/doric/shader/list/ListAdapter.java index dc95cfa4..955d42d0 100644 --- a/doric/src/main/java/pub/doric/shader/list/ListAdapter.java +++ b/doric/src/main/java/pub/doric/shader/list/ListAdapter.java @@ -16,7 +16,6 @@ package pub.doric.shader.list; import android.text.TextUtils; -import android.util.SparseArray; import android.view.View; import android.view.ViewGroup; @@ -40,10 +39,6 @@ import pub.doric.shader.ViewNode; class ListAdapter extends RecyclerView.Adapter { private final ListNode listNode; - String renderItemFuncId; - int itemCount = 0; - int batchCount = 15; - SparseArray itemValues = new SparseArray<>(); ListAdapter(ListNode listNode) { this.listNode = listNode; @@ -65,15 +60,21 @@ class ListAdapter extends RecyclerView.Adapter { holder.listItemNode.setId(jsObject.getProperty("id").asString().value()); holder.listItemNode.blend(jsObject.getProperty("props").asObject()); } + if (position >= this.listNode.itemCount) { + this.listNode.callJSResponse(this.listNode.onLoadMoreFuncId); + } } @Override public int getItemCount() { - return itemCount; + return this.listNode.itemCount + (this.listNode.loadMore ? 1 : 0); } @Override public int getItemViewType(int position) { + if (position >= this.listNode.itemCount) { + return Integer.MAX_VALUE; + } JSValue value = getItemModel(position); if (value != null && value.isObject()) { if (value.asObject().getProperty("identifier").isString()) { @@ -84,12 +85,15 @@ class ListAdapter extends RecyclerView.Adapter { } private JSValue getItemModel(final int position) { - String id = itemValues.get(position); + if (position >= this.listNode.itemCount) { + return this.listNode.getSubModel(this.listNode.loadMoreViewId); + } + String id = listNode.itemValues.get(position); if (TextUtils.isEmpty(id)) { AsyncResult asyncResult = listNode.callJSResponse( "renderBunchedItems", position, - batchCount); + listNode.batchCount); try { JSDecoder jsDecoder = asyncResult.synchronous().get(); JSValue result = jsDecoder.decode(); @@ -98,10 +102,10 @@ class ListAdapter extends RecyclerView.Adapter { for (int i = 0; i < jsArray.size(); i++) { JSObject itemModel = jsArray.get(i).asObject(); String itemId = itemModel.getProperty("id").asString().value(); - itemValues.put(i + position, itemId); + listNode.itemValues.put(i + position, itemId); listNode.setSubModel(itemId, itemModel); } - return listNode.getSubModel(itemValues.get(position)); + return listNode.getSubModel(listNode.itemValues.get(position)); } } catch (Exception e) { e.printStackTrace(); @@ -119,8 +123,8 @@ class ListAdapter extends RecyclerView.Adapter { void blendSubNode(JSObject subProperties) { - for (int i = 0; i < itemValues.size(); i++) { - if (subProperties.getProperty("id").asString().value().equals(itemValues.valueAt(i))) { + for (int i = 0; i < listNode.itemValues.size(); i++) { + if (subProperties.getProperty("id").asString().value().equals(listNode.itemValues.valueAt(i))) { notifyItemChanged(i); } } diff --git a/doric/src/main/java/pub/doric/shader/list/ListNode.java b/doric/src/main/java/pub/doric/shader/list/ListNode.java index 75f0da8d..4c2316c2 100644 --- a/doric/src/main/java/pub/doric/shader/list/ListNode.java +++ b/doric/src/main/java/pub/doric/shader/list/ListNode.java @@ -15,6 +15,7 @@ */ package pub.doric.shader.list; +import android.util.SparseArray; import android.view.View; import androidx.recyclerview.widget.LinearLayoutManager; @@ -36,6 +37,13 @@ import pub.doric.shader.ViewNode; @DoricPlugin(name = "List") public class ListNode extends SuperNode { private final ListAdapter listAdapter; + private String renderItemFuncId; + String onLoadMoreFuncId; + int itemCount = 0; + int batchCount = 15; + SparseArray itemValues = new SparseArray<>(); + boolean loadMore = false; + String loadMoreViewId; public ListNode(DoricContext doricContext) { super(doricContext); @@ -82,19 +90,30 @@ public class ListNode extends SuperNode { protected void blend(RecyclerView view, String name, JSValue prop) { switch (name) { case "itemCount": - this.listAdapter.itemCount = prop.asNumber().toInt(); + this.itemCount = prop.asNumber().toInt(); break; case "renderItem": String funcId = prop.asString().value(); - if (!funcId.equals(this.listAdapter.renderItemFuncId)) { - this.listAdapter.renderItemFuncId = funcId; + if (!funcId.equals(this.renderItemFuncId)) { + this.renderItemFuncId = funcId; // If reset renderItem,should reset native cache. - this.listAdapter.itemValues.clear(); - clearSubModel(); + for (int index = 0; index < this.itemValues.size(); index++) { + removeSubModel(this.itemValues.valueAt(index)); + } + this.itemValues.clear(); } break; + case "onLoadMore": + this.onLoadMoreFuncId = prop.asString().value(); + break; + case "loadMoreView": + this.loadMoreViewId = prop.asString().value(); + break; case "batchCount": - this.listAdapter.batchCount = prop.asNumber().toInt(); + this.batchCount = prop.asNumber().toInt(); + break; + case "loadMore": + this.loadMore = prop.asBoolean().value(); break; default: super.blend(view, name, prop);