feat:refact render child in groupNode

This commit is contained in:
pengfei.zhou 2019-11-14 17:57:12 +08:00
parent 74d31edc26
commit d2f4302e42
6 changed files with 155 additions and 138 deletions

View File

@ -16,6 +16,7 @@
package pub.doric.plugin;
import pub.doric.DoricContext;
import pub.doric.async.AsyncResult;
import pub.doric.extension.bridge.DoricMethod;
import pub.doric.extension.bridge.DoricPlugin;
import pub.doric.utils.DoricLog;
@ -49,7 +50,23 @@ public class ShaderPlugin extends DoricJavaPlugin {
rootNode.render(jsObject.getProperty("props").asObject());
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) {
e.printStackTrace();
DoricLog.e("Shader.render:error%s", e.getLocalizedMessage());

View File

@ -15,7 +15,6 @@
*/
package pub.doric.shader;
import android.util.SparseArray;
import android.view.ViewGroup;
import pub.doric.DoricContext;
@ -25,9 +24,6 @@ import com.github.pengfeizhou.jscore.JSObject;
import com.github.pengfeizhou.jscore.JSValue;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Description: com.github.penfeizhou.doric.widget
@ -35,8 +31,8 @@ import java.util.Map;
* @CreateDate: 2019-07-20
*/
public abstract class GroupNode<F extends ViewGroup> extends SuperNode<F> {
private Map<String, ViewNode> mChildrenNode = new HashMap<>();
private SparseArray<ViewNode> mIndexInfo = new SparseArray<>();
private ArrayList<ViewNode> mChildNodes = new ArrayList<>();
private ArrayList<String> mChildViewIds = new ArrayList<>();
public GroupNode(DoricContext doricContext) {
super(doricContext);
@ -45,80 +41,90 @@ public abstract class GroupNode<F extends ViewGroup> extends SuperNode<F> {
@Override
protected void blend(F view, ViewGroup.LayoutParams layoutParams, String name, JSValue prop) {
if ("children".equals(name)) {
JSArray jsArray = prop.asArray();
int i;
List<ViewNode> tobeRemoved = new ArrayList<>();
for (i = 0; i < jsArray.size(); i++) {
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);
}
JSArray ids = prop.asArray();
mChildViewIds.clear();
for (int i = 0; i < ids.size(); i++) {
mChildViewIds.add(ids.get(i).asString().value());
}
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 {
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
protected void blendSubNode(JSObject subProp) {
String subNodeId = subProp.getProperty("id").asString().value();
for (ViewNode node : mChildrenNode.values()) {
for (ViewNode node : mChildNodes) {
if (subNodeId.equals(node.getId())) {
node.blend(subProp, node.getLayoutParams());
node.blend(subProp.getProperty("props").asObject(), node.getLayoutParams());
break;
}
}
}

View File

@ -22,6 +22,9 @@ import com.github.pengfeizhou.jscore.JSArray;
import com.github.pengfeizhou.jscore.JSObject;
import com.github.pengfeizhou.jscore.JSValue;
import java.util.HashMap;
import java.util.Map;
import pub.doric.DoricContext;
import pub.doric.utils.DoricUtils;
@ -31,6 +34,8 @@ import pub.doric.utils.DoricUtils;
* @CreateDate: 2019-11-13
*/
public abstract class SuperNode<V extends View> extends ViewNode<V> {
private Map<String, JSObject> subNodes = new HashMap<>();
public SuperNode(DoricContext doricContext) {
super(doricContext);
}
@ -42,16 +47,33 @@ public abstract class SuperNode<V extends View> extends ViewNode<V> {
@Override
protected void blend(V view, ViewGroup.LayoutParams layoutParams, String name, JSValue prop) {
if (name.equals("subviews")) {
JSArray subviews = prop.asArray();
for (int i = 0; i < subviews.size(); i++) {
JSObject subProp = subviews.get(i).asObject();
blendSubNode(subProp);
if (prop.isArray()) {
JSArray subviews = prop.asArray();
for (int i = 0; i < subviews.size(); i++) {
JSObject subNode = subviews.get(i).asObject();
mixinSubNode(subNode);
blendSubNode(subNode);
}
}
} else {
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 void blendSubLayoutConfig(ViewNode viewNode, JSObject jsObject) {
@ -70,7 +92,6 @@ public abstract class SuperNode<V extends View> extends ViewNode<V> {
break;
default:
break;
}
}
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);
}
}
}
}

View File

@ -27,9 +27,6 @@ import com.github.pengfeizhou.jscore.JSDecoder;
import com.github.pengfeizhou.jscore.JSObject;
import com.github.pengfeizhou.jscore.JSValue;
import org.json.JSONObject;
import pub.doric.async.AsyncResult;
import pub.doric.shader.ViewNode;
@ -111,54 +108,9 @@ public class ListAdapter extends RecyclerView.Adapter<ListAdapter.DoricViewHolde
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 {
ListItemNode listItemNode;

View File

@ -70,7 +70,7 @@ export class List extends Superview implements IList {
private renderBunchedItems(start: number, length: number) {
return new Array(Math.min(length, this.itemCount - start)).fill(0).map((_, idx) => {
const listItem = this.getItem(start + idx)
return listItem.toModel()
return listItem.viewId
})
}
}

View File

@ -303,7 +303,7 @@ export abstract class Group extends Superview {
set: (target, index, value) => {
const ret = Reflect.set(target, index, value)
// Let getDirty return true
this.dirtyProps.children = []
this.dirtyProps.children = this.children.map(e => e.viewId)
return ret
}
})
@ -315,17 +315,5 @@ export abstract class Group extends Superview {
addChild(view: 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
}
}