feat:refact render child in groupNode
This commit is contained in:
parent
74d31edc26
commit
d2f4302e42
@ -16,6 +16,7 @@
|
|||||||
package pub.doric.plugin;
|
package pub.doric.plugin;
|
||||||
|
|
||||||
import pub.doric.DoricContext;
|
import pub.doric.DoricContext;
|
||||||
|
import pub.doric.async.AsyncResult;
|
||||||
import pub.doric.extension.bridge.DoricMethod;
|
import pub.doric.extension.bridge.DoricMethod;
|
||||||
import pub.doric.extension.bridge.DoricPlugin;
|
import pub.doric.extension.bridge.DoricPlugin;
|
||||||
import pub.doric.utils.DoricLog;
|
import pub.doric.utils.DoricLog;
|
||||||
@ -49,7 +50,23 @@ public class ShaderPlugin extends DoricJavaPlugin {
|
|||||||
rootNode.render(jsObject.getProperty("props").asObject());
|
rootNode.render(jsObject.getProperty("props").asObject());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}, ThreadMode.UI);
|
}, ThreadMode.UI).setCallback(new AsyncResult.Callback<Object>() {
|
||||||
|
@Override
|
||||||
|
public void onResult(Object result) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Throwable t) {
|
||||||
|
t.printStackTrace();
|
||||||
|
DoricLog.e("Shader.render:error%s", t.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFinish() {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
DoricLog.e("Shader.render:error%s", e.getLocalizedMessage());
|
DoricLog.e("Shader.render:error%s", e.getLocalizedMessage());
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package pub.doric.shader;
|
package pub.doric.shader;
|
||||||
|
|
||||||
import android.util.SparseArray;
|
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import pub.doric.DoricContext;
|
import pub.doric.DoricContext;
|
||||||
@ -25,9 +24,6 @@ import com.github.pengfeizhou.jscore.JSObject;
|
|||||||
import com.github.pengfeizhou.jscore.JSValue;
|
import com.github.pengfeizhou.jscore.JSValue;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: com.github.penfeizhou.doric.widget
|
* @Description: com.github.penfeizhou.doric.widget
|
||||||
@ -35,8 +31,8 @@ import java.util.Map;
|
|||||||
* @CreateDate: 2019-07-20
|
* @CreateDate: 2019-07-20
|
||||||
*/
|
*/
|
||||||
public abstract class GroupNode<F extends ViewGroup> extends SuperNode<F> {
|
public abstract class GroupNode<F extends ViewGroup> extends SuperNode<F> {
|
||||||
private Map<String, ViewNode> mChildrenNode = new HashMap<>();
|
private ArrayList<ViewNode> mChildNodes = new ArrayList<>();
|
||||||
private SparseArray<ViewNode> mIndexInfo = new SparseArray<>();
|
private ArrayList<String> mChildViewIds = new ArrayList<>();
|
||||||
|
|
||||||
public GroupNode(DoricContext doricContext) {
|
public GroupNode(DoricContext doricContext) {
|
||||||
super(doricContext);
|
super(doricContext);
|
||||||
@ -45,80 +41,90 @@ public abstract class GroupNode<F extends ViewGroup> extends SuperNode<F> {
|
|||||||
@Override
|
@Override
|
||||||
protected void blend(F view, ViewGroup.LayoutParams layoutParams, String name, JSValue prop) {
|
protected void blend(F view, ViewGroup.LayoutParams layoutParams, String name, JSValue prop) {
|
||||||
if ("children".equals(name)) {
|
if ("children".equals(name)) {
|
||||||
JSArray jsArray = prop.asArray();
|
JSArray ids = prop.asArray();
|
||||||
int i;
|
mChildViewIds.clear();
|
||||||
List<ViewNode> tobeRemoved = new ArrayList<>();
|
for (int i = 0; i < ids.size(); i++) {
|
||||||
for (i = 0; i < jsArray.size(); i++) {
|
mChildViewIds.add(ids.get(i).asString().value());
|
||||||
JSValue jsValue = jsArray.get(i);
|
|
||||||
if (!jsValue.isObject()) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
JSObject childObj = jsValue.asObject();
|
|
||||||
String type = childObj.getProperty("type").asString().value();
|
|
||||||
String id = childObj.getProperty("id").asString().value();
|
|
||||||
ViewNode child = mChildrenNode.get(id);
|
|
||||||
if (child == null) {
|
|
||||||
child = ViewNode.create(getDoricContext(), type);
|
|
||||||
child.index = i;
|
|
||||||
child.mSuperNode = this;
|
|
||||||
child.mId = id;
|
|
||||||
mChildrenNode.put(id, child);
|
|
||||||
} else {
|
|
||||||
if (i != child.index) {
|
|
||||||
mIndexInfo.remove(i);
|
|
||||||
child.index = i;
|
|
||||||
mView.removeView(child.getDoricLayer());
|
|
||||||
}
|
|
||||||
tobeRemoved.remove(child);
|
|
||||||
}
|
|
||||||
|
|
||||||
ViewNode node = mIndexInfo.get(i);
|
|
||||||
|
|
||||||
if (node != null && node != child) {
|
|
||||||
mView.removeViewAt(i);
|
|
||||||
mIndexInfo.remove(i);
|
|
||||||
tobeRemoved.add(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
ViewGroup.LayoutParams params = child.getLayoutParams();
|
|
||||||
if (params == null) {
|
|
||||||
params = generateDefaultLayoutParams();
|
|
||||||
}
|
|
||||||
child.blend(childObj.getProperty("props").asObject(), params);
|
|
||||||
if (mIndexInfo.get(i) == null) {
|
|
||||||
mView.addView(child.getDoricLayer(), i, child.getLayoutParams());
|
|
||||||
mIndexInfo.put(i, child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int count = mView.getChildCount();
|
|
||||||
while (i < count) {
|
|
||||||
ViewNode node = mIndexInfo.get(i);
|
|
||||||
if (node != null) {
|
|
||||||
mChildrenNode.remove(node.getId());
|
|
||||||
mIndexInfo.remove(i);
|
|
||||||
tobeRemoved.remove(node);
|
|
||||||
mView.removeView(node.getDoricLayer());
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ViewNode node : tobeRemoved) {
|
|
||||||
mChildrenNode.remove(node.getId());
|
|
||||||
}
|
|
||||||
} else if ("subviews".equals(name)) {
|
|
||||||
// Currently do nothing,because its subview always contained in props.children
|
|
||||||
// super.blend(view, layoutParams, name, prop);
|
|
||||||
} else {
|
} else {
|
||||||
super.blend(view, layoutParams, name, prop);
|
super.blend(view, layoutParams, name, prop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void blend(JSObject jsObject, ViewGroup.LayoutParams layoutParams) {
|
||||||
|
super.blend(jsObject, layoutParams);
|
||||||
|
configChildNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void configChildNode() {
|
||||||
|
for (int idx = 0; idx < mChildViewIds.size(); idx++) {
|
||||||
|
String id = mChildViewIds.get(idx);
|
||||||
|
JSObject model = getSubModel(id);
|
||||||
|
String type = model.getProperty("type").asString().value();
|
||||||
|
if (idx < mChildNodes.size()) {
|
||||||
|
ViewNode oldNode = mChildNodes.get(idx);
|
||||||
|
if (id.equals(oldNode.getId())) {
|
||||||
|
//The same,skip
|
||||||
|
} else {
|
||||||
|
//Find in remaining nodes
|
||||||
|
int position = -1;
|
||||||
|
for (int start = idx + 1; start < mChildNodes.size(); start++) {
|
||||||
|
ViewNode node = mChildNodes.get(start);
|
||||||
|
if (id.equals(node.getId())) {
|
||||||
|
//Found
|
||||||
|
position = start;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (position >= 0) {
|
||||||
|
//Found swap idx,position
|
||||||
|
ViewNode reused = mChildNodes.remove(position);
|
||||||
|
ViewNode abandoned = mChildNodes.remove(idx);
|
||||||
|
mChildNodes.set(idx, reused);
|
||||||
|
mChildNodes.set(position, abandoned);
|
||||||
|
//View swap index
|
||||||
|
mView.removeView(reused.getDoricLayer());
|
||||||
|
mView.addView(reused.getDoricLayer(), idx);
|
||||||
|
mView.removeView(abandoned.getDoricLayer());
|
||||||
|
mView.addView(abandoned.getDoricLayer(), position);
|
||||||
|
} else {
|
||||||
|
//Not found,insert
|
||||||
|
ViewNode newNode = ViewNode.create(getDoricContext(), type);
|
||||||
|
newNode.setSuperNode(this);
|
||||||
|
newNode.setId(id);
|
||||||
|
ViewGroup.LayoutParams params = generateDefaultLayoutParams();
|
||||||
|
newNode.blend(model.getProperty("props").asObject(), params);
|
||||||
|
|
||||||
|
mChildNodes.set(idx, newNode);
|
||||||
|
mView.addView(newNode.getDoricLayer(), idx, newNode.getLayoutParams());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//Insert
|
||||||
|
ViewNode newNode = ViewNode.create(getDoricContext(), type);
|
||||||
|
newNode.setSuperNode(this);
|
||||||
|
newNode.setId(id);
|
||||||
|
ViewGroup.LayoutParams params = generateDefaultLayoutParams();
|
||||||
|
newNode.blend(model.getProperty("props").asObject(), params);
|
||||||
|
mChildNodes.add(newNode);
|
||||||
|
mView.addView(newNode.getDoricLayer(), idx, newNode.getLayoutParams());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int size = mChildNodes.size();
|
||||||
|
for (int idx = mChildViewIds.size(); idx < size; idx++) {
|
||||||
|
ViewNode viewNode = mChildNodes.remove(mChildViewIds.size());
|
||||||
|
mView.removeView(viewNode.getDoricLayer());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void blendSubNode(JSObject subProp) {
|
protected void blendSubNode(JSObject subProp) {
|
||||||
String subNodeId = subProp.getProperty("id").asString().value();
|
String subNodeId = subProp.getProperty("id").asString().value();
|
||||||
for (ViewNode node : mChildrenNode.values()) {
|
for (ViewNode node : mChildNodes) {
|
||||||
if (subNodeId.equals(node.getId())) {
|
if (subNodeId.equals(node.getId())) {
|
||||||
node.blend(subProp, node.getLayoutParams());
|
node.blend(subProp.getProperty("props").asObject(), node.getLayoutParams());
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,9 @@ import com.github.pengfeizhou.jscore.JSArray;
|
|||||||
import com.github.pengfeizhou.jscore.JSObject;
|
import com.github.pengfeizhou.jscore.JSObject;
|
||||||
import com.github.pengfeizhou.jscore.JSValue;
|
import com.github.pengfeizhou.jscore.JSValue;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import pub.doric.DoricContext;
|
import pub.doric.DoricContext;
|
||||||
import pub.doric.utils.DoricUtils;
|
import pub.doric.utils.DoricUtils;
|
||||||
|
|
||||||
@ -31,6 +34,8 @@ import pub.doric.utils.DoricUtils;
|
|||||||
* @CreateDate: 2019-11-13
|
* @CreateDate: 2019-11-13
|
||||||
*/
|
*/
|
||||||
public abstract class SuperNode<V extends View> extends ViewNode<V> {
|
public abstract class SuperNode<V extends View> extends ViewNode<V> {
|
||||||
|
private Map<String, JSObject> subNodes = new HashMap<>();
|
||||||
|
|
||||||
public SuperNode(DoricContext doricContext) {
|
public SuperNode(DoricContext doricContext) {
|
||||||
super(doricContext);
|
super(doricContext);
|
||||||
}
|
}
|
||||||
@ -42,16 +47,33 @@ public abstract class SuperNode<V extends View> extends ViewNode<V> {
|
|||||||
@Override
|
@Override
|
||||||
protected void blend(V view, ViewGroup.LayoutParams layoutParams, String name, JSValue prop) {
|
protected void blend(V view, ViewGroup.LayoutParams layoutParams, String name, JSValue prop) {
|
||||||
if (name.equals("subviews")) {
|
if (name.equals("subviews")) {
|
||||||
|
if (prop.isArray()) {
|
||||||
JSArray subviews = prop.asArray();
|
JSArray subviews = prop.asArray();
|
||||||
for (int i = 0; i < subviews.size(); i++) {
|
for (int i = 0; i < subviews.size(); i++) {
|
||||||
JSObject subProp = subviews.get(i).asObject();
|
JSObject subNode = subviews.get(i).asObject();
|
||||||
blendSubNode(subProp);
|
mixinSubNode(subNode);
|
||||||
|
blendSubNode(subNode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
super.blend(view, layoutParams, name, prop);
|
super.blend(view, layoutParams, name, prop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void mixinSubNode(JSObject subNode) {
|
||||||
|
String id = subNode.getProperty("id").asString().value();
|
||||||
|
JSObject targetNode = subNodes.get(id);
|
||||||
|
if (targetNode == null) {
|
||||||
|
subNodes.put(id, subNode);
|
||||||
|
} else {
|
||||||
|
mixin(subNode, targetNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public JSObject getSubModel(String id) {
|
||||||
|
return subNodes.get(id);
|
||||||
|
}
|
||||||
|
|
||||||
protected abstract void blendSubNode(JSObject subProperties);
|
protected abstract void blendSubNode(JSObject subProperties);
|
||||||
|
|
||||||
protected void blendSubLayoutConfig(ViewNode viewNode, JSObject jsObject) {
|
protected void blendSubLayoutConfig(ViewNode viewNode, JSObject jsObject) {
|
||||||
@ -70,7 +92,6 @@ public abstract class SuperNode<V extends View> extends ViewNode<V> {
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (heightSpec.isNumber()) {
|
if (heightSpec.isNumber()) {
|
||||||
@ -104,4 +125,37 @@ public abstract class SuperNode<V extends View> extends ViewNode<V> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void mixin(JSObject src, JSObject target) {
|
||||||
|
JSValue srcProps = src.getProperty("props");
|
||||||
|
JSValue targetProps = target.getProperty("props");
|
||||||
|
if (srcProps.isObject()) {
|
||||||
|
if (targetProps.isObject()) {
|
||||||
|
for (String key : srcProps.asObject().propertySet()) {
|
||||||
|
JSValue jsValue = srcProps.asObject().getProperty(key);
|
||||||
|
if ("children".equals(key) && jsValue.isArray()) {
|
||||||
|
JSValue targetChildren = targetProps.asObject().getProperty("children");
|
||||||
|
if (targetChildren.isArray() && targetChildren.asArray().size() == jsValue.asArray().size()) {
|
||||||
|
for (int i = 0; i < jsValue.asArray().size(); i++) {
|
||||||
|
JSValue childSrc = jsValue.asArray().get(i);
|
||||||
|
JSValue childTarget = targetChildren.asArray().get(i);
|
||||||
|
if (childSrc.isObject()) {
|
||||||
|
if (childTarget.isObject()) {
|
||||||
|
mixin(childSrc.asObject(), childTarget.asObject());
|
||||||
|
} else {
|
||||||
|
targetChildren.asArray().put(i, childSrc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
targetProps.asObject().setProperty(key, jsValue);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
target.setProperty("props", srcProps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -27,9 +27,6 @@ import com.github.pengfeizhou.jscore.JSDecoder;
|
|||||||
import com.github.pengfeizhou.jscore.JSObject;
|
import com.github.pengfeizhou.jscore.JSObject;
|
||||||
import com.github.pengfeizhou.jscore.JSValue;
|
import com.github.pengfeizhou.jscore.JSValue;
|
||||||
|
|
||||||
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import pub.doric.async.AsyncResult;
|
import pub.doric.async.AsyncResult;
|
||||||
import pub.doric.shader.ViewNode;
|
import pub.doric.shader.ViewNode;
|
||||||
|
|
||||||
@ -111,53 +108,8 @@ public class ListAdapter extends RecyclerView.Adapter<ListAdapter.DoricViewHolde
|
|||||||
|
|
||||||
|
|
||||||
void blendSubNode(JSObject subProperties) {
|
void blendSubNode(JSObject subProperties) {
|
||||||
String subNodeId = subProperties.getProperty("id").asString().value();
|
|
||||||
for (int i = 0; i < itemValues.size(); i++) {
|
|
||||||
JSValue jsValue = itemValues.valueAt(i);
|
|
||||||
if (jsValue.isObject()) {
|
|
||||||
JSObject jsObject = jsValue.asObject();
|
|
||||||
if (subNodeId.equals(jsObject.getProperty("id").asString().value())) {
|
|
||||||
mixin(subProperties, jsObject);
|
|
||||||
int position = itemValues.keyAt(i);
|
|
||||||
notifyItemChanged(position);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void mixin(JSObject src, JSObject target) {
|
|
||||||
JSValue srcProps = src.getProperty("props");
|
|
||||||
JSValue targetProps = target.getProperty("props");
|
|
||||||
if (srcProps.isObject()) {
|
|
||||||
if (targetProps.isObject()) {
|
|
||||||
for (String key : srcProps.asObject().propertySet()) {
|
|
||||||
JSValue jsValue = srcProps.asObject().getProperty(key);
|
|
||||||
if ("children".equals(key) && jsValue.isArray()) {
|
|
||||||
JSValue targetChildren = targetProps.asObject().getProperty("children");
|
|
||||||
if (targetChildren.isArray() && targetChildren.asArray().size() == jsValue.asArray().size()) {
|
|
||||||
for (int i = 0; i < jsValue.asArray().size(); i++) {
|
|
||||||
JSValue childSrc = jsValue.asArray().get(i);
|
|
||||||
JSValue childTarget = targetChildren.asArray().get(i);
|
|
||||||
if (childSrc.isObject()) {
|
|
||||||
if (childTarget.isObject()) {
|
|
||||||
mixin(childSrc.asObject(), childTarget.asObject());
|
|
||||||
} else {
|
|
||||||
targetChildren.asArray().put(i, childSrc);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
targetProps.asObject().setProperty(key, jsValue);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
target.setProperty("props", srcProps);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static class DoricViewHolder extends RecyclerView.ViewHolder {
|
static class DoricViewHolder extends RecyclerView.ViewHolder {
|
||||||
ListItemNode listItemNode;
|
ListItemNode listItemNode;
|
||||||
|
@ -70,7 +70,7 @@ export class List extends Superview implements IList {
|
|||||||
private renderBunchedItems(start: number, length: number) {
|
private renderBunchedItems(start: number, length: number) {
|
||||||
return new Array(Math.min(length, this.itemCount - start)).fill(0).map((_, idx) => {
|
return new Array(Math.min(length, this.itemCount - start)).fill(0).map((_, idx) => {
|
||||||
const listItem = this.getItem(start + idx)
|
const listItem = this.getItem(start + idx)
|
||||||
return listItem.toModel()
|
return listItem.viewId
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -303,7 +303,7 @@ export abstract class Group extends Superview {
|
|||||||
set: (target, index, value) => {
|
set: (target, index, value) => {
|
||||||
const ret = Reflect.set(target, index, value)
|
const ret = Reflect.set(target, index, value)
|
||||||
// Let getDirty return true
|
// Let getDirty return true
|
||||||
this.dirtyProps.children = []
|
this.dirtyProps.children = this.children.map(e => e.viewId)
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -315,17 +315,5 @@ export abstract class Group extends Superview {
|
|||||||
addChild(view: View) {
|
addChild(view: View) {
|
||||||
this.children.push(view)
|
this.children.push(view)
|
||||||
}
|
}
|
||||||
|
|
||||||
toModel() {
|
|
||||||
this.dirtyProps.children = this.children.map(e => {
|
|
||||||
if (e.isDirty()) {
|
|
||||||
return e.toModel()
|
|
||||||
} else {
|
|
||||||
//Dont need return model
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return this.nativeViewModel
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user