Initial FlatUIImplemenatation
Summary: public This patch adds an alternative UIImplementation based on an idea of creating UI hierarchy off-the-main-thread (everything but Views), flattening ReactShadowNode hierarchy and displaying it within a single View when possible. While NativeViewHierarchyOptimizer allows removing layout-only RCTViews, this allows removing RCTView, RCTText and RCTImage. This is an initial bare-bones implementation that doesn't really draw anything, only lays out the shadow nodes. Followup diffs will add missing features. Reviewed By: astreet Differential Revision: D2564309 fb-gh-sync-id: 2dda4c8cfc2bac3eb39c5c15e97bd23a57550a1d
This commit is contained in:
parent
b0e39d26ae
commit
b828ae4200
|
@ -41,15 +41,40 @@ public class UIImplementation {
|
||||||
private final int[] mMeasureBuffer = new int[4];
|
private final int[] mMeasureBuffer = new int[4];
|
||||||
|
|
||||||
public UIImplementation(ReactApplicationContext reactContext, List<ViewManager> viewManagers) {
|
public UIImplementation(ReactApplicationContext reactContext, List<ViewManager> viewManagers) {
|
||||||
mViewManagers = new ViewManagerRegistry(viewManagers);
|
this(reactContext, new ViewManagerRegistry(viewManagers));
|
||||||
mOperationsQueue = new UIViewOperationQueue(
|
}
|
||||||
reactContext,
|
|
||||||
new NativeViewHierarchyManager(mViewManagers));
|
private UIImplementation(ReactApplicationContext reactContext, ViewManagerRegistry viewManagers) {
|
||||||
|
this(
|
||||||
|
viewManagers,
|
||||||
|
new UIViewOperationQueue(reactContext, new NativeViewHierarchyManager(viewManagers)));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected UIImplementation(
|
||||||
|
ViewManagerRegistry viewManagers,
|
||||||
|
UIViewOperationQueue operationsQueue) {
|
||||||
|
mViewManagers = viewManagers;
|
||||||
|
mOperationsQueue = operationsQueue;
|
||||||
mNativeViewHierarchyOptimizer = new NativeViewHierarchyOptimizer(
|
mNativeViewHierarchyOptimizer = new NativeViewHierarchyOptimizer(
|
||||||
mOperationsQueue,
|
mOperationsQueue,
|
||||||
mShadowNodeRegistry);
|
mShadowNodeRegistry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected ReactShadowNode createRootShadowNode() {
|
||||||
|
ReactShadowNode rootCSSNode = new ReactShadowNode();
|
||||||
|
rootCSSNode.setViewClassName("Root");
|
||||||
|
return rootCSSNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ReactShadowNode createShadowNode(String className) {
|
||||||
|
ViewManager viewManager = mViewManagers.get(className);
|
||||||
|
return viewManager.createShadowNodeInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final ReactShadowNode resolveShadowNode(int reactTag) {
|
||||||
|
return mShadowNodeRegistry.getNode(reactTag);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a root node with a given tag, size and ThemedReactContext
|
* Registers a root node with a given tag, size and ThemedReactContext
|
||||||
* and adds it to a node registry.
|
* and adds it to a node registry.
|
||||||
|
@ -60,12 +85,11 @@ public class UIImplementation {
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
ThemedReactContext context) {
|
ThemedReactContext context) {
|
||||||
final ReactShadowNode rootCSSNode = new ReactShadowNode();
|
final ReactShadowNode rootCSSNode = createRootShadowNode();
|
||||||
rootCSSNode.setReactTag(tag);
|
rootCSSNode.setReactTag(tag);
|
||||||
rootCSSNode.setThemedContext(context);
|
rootCSSNode.setThemedContext(context);
|
||||||
rootCSSNode.setStyleWidth(width);
|
rootCSSNode.setStyleWidth(width);
|
||||||
rootCSSNode.setStyleHeight(height);
|
rootCSSNode.setStyleHeight(height);
|
||||||
rootCSSNode.setViewClassName("Root");
|
|
||||||
mShadowNodeRegistry.addRootNode(rootCSSNode);
|
mShadowNodeRegistry.addRootNode(rootCSSNode);
|
||||||
|
|
||||||
// register it within NativeViewHierarchyManager
|
// register it within NativeViewHierarchyManager
|
||||||
|
@ -104,8 +128,7 @@ public class UIImplementation {
|
||||||
* Invoked by React to create a new node with a given tag, class name and properties.
|
* Invoked by React to create a new node with a given tag, class name and properties.
|
||||||
*/
|
*/
|
||||||
public void createView(int tag, String className, int rootViewTag, ReadableMap props) {
|
public void createView(int tag, String className, int rootViewTag, ReadableMap props) {
|
||||||
ViewManager viewManager = mViewManagers.get(className);
|
ReactShadowNode cssNode = createShadowNode(className);
|
||||||
ReactShadowNode cssNode = viewManager.createShadowNodeInstance();
|
|
||||||
ReactShadowNode rootNode = mShadowNodeRegistry.getNode(rootViewTag);
|
ReactShadowNode rootNode = mShadowNodeRegistry.getNode(rootViewTag);
|
||||||
cssNode.setReactTag(tag);
|
cssNode.setReactTag(tag);
|
||||||
cssNode.setViewClassName(className);
|
cssNode.setViewClassName(className);
|
||||||
|
@ -120,8 +143,15 @@ public class UIImplementation {
|
||||||
cssNode.updateProperties(styles);
|
cssNode.updateProperties(styles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleCreateView(cssNode, rootViewTag, styles);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void handleCreateView(
|
||||||
|
ReactShadowNode cssNode,
|
||||||
|
int rootViewTag,
|
||||||
|
@Nullable CatalystStylesDiffMap styles) {
|
||||||
if (!cssNode.isVirtual()) {
|
if (!cssNode.isVirtual()) {
|
||||||
mNativeViewHierarchyOptimizer.handleCreateView(cssNode, rootNode.getThemedContext(), styles);
|
mNativeViewHierarchyOptimizer.handleCreateView(cssNode, cssNode.getThemedContext(), styles);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,11 +171,18 @@ public class UIImplementation {
|
||||||
if (props != null) {
|
if (props != null) {
|
||||||
CatalystStylesDiffMap styles = new CatalystStylesDiffMap(props);
|
CatalystStylesDiffMap styles = new CatalystStylesDiffMap(props);
|
||||||
cssNode.updateProperties(styles);
|
cssNode.updateProperties(styles);
|
||||||
|
handleUpdateView(cssNode, className, styles);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void handleUpdateView(
|
||||||
|
ReactShadowNode cssNode,
|
||||||
|
String className,
|
||||||
|
CatalystStylesDiffMap styles) {
|
||||||
if (!cssNode.isVirtual()) {
|
if (!cssNode.isVirtual()) {
|
||||||
mNativeViewHierarchyOptimizer.handleUpdateView(cssNode, className, styles);
|
mNativeViewHierarchyOptimizer.handleUpdateView(cssNode, className, styles);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked when there is a mutation in a node tree.
|
* Invoked when there is a mutation in a node tree.
|
||||||
|
@ -401,14 +438,7 @@ public class UIImplementation {
|
||||||
ReactShadowNode cssRoot = mShadowNodeRegistry.getNode(tag);
|
ReactShadowNode cssRoot = mShadowNodeRegistry.getNode(tag);
|
||||||
notifyOnBeforeLayoutRecursive(cssRoot);
|
notifyOnBeforeLayoutRecursive(cssRoot);
|
||||||
|
|
||||||
SystraceMessage.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "cssRoot.calculateLayout")
|
calculateRootLayout(cssRoot);
|
||||||
.arg("rootTag", tag)
|
|
||||||
.flush();
|
|
||||||
try {
|
|
||||||
cssRoot.calculateLayout(mLayoutContext);
|
|
||||||
} finally {
|
|
||||||
Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
|
|
||||||
}
|
|
||||||
applyUpdatesRecursive(cssRoot, 0f, 0f, eventDispatcher);
|
applyUpdatesRecursive(cssRoot, 0f, 0f, eventDispatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -492,7 +522,7 @@ public class UIImplementation {
|
||||||
mOperationsQueue.setViewHierarchyUpdateDebugListener(listener);
|
mOperationsQueue.setViewHierarchyUpdateDebugListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeShadowNode(ReactShadowNode nodeToRemove) {
|
protected final void removeShadowNode(ReactShadowNode nodeToRemove) {
|
||||||
mNativeViewHierarchyOptimizer.handleRemoveNode(nodeToRemove);
|
mNativeViewHierarchyOptimizer.handleRemoveNode(nodeToRemove);
|
||||||
mShadowNodeRegistry.removeNode(nodeToRemove.getReactTag());
|
mShadowNodeRegistry.removeNode(nodeToRemove.getReactTag());
|
||||||
for (int i = nodeToRemove.getChildCount() - 1; i >= 0; i--) {
|
for (int i = nodeToRemove.getChildCount() - 1; i >= 0; i--) {
|
||||||
|
@ -597,7 +627,18 @@ public class UIImplementation {
|
||||||
cssNode.onBeforeLayout();
|
cssNode.onBeforeLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyUpdatesRecursive(
|
protected void calculateRootLayout(ReactShadowNode cssRoot) {
|
||||||
|
SystraceMessage.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "cssRoot.calculateLayout")
|
||||||
|
.arg("rootTag", cssRoot.getReactTag())
|
||||||
|
.flush();
|
||||||
|
try {
|
||||||
|
cssRoot.calculateLayout(mLayoutContext);
|
||||||
|
} finally {
|
||||||
|
Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void applyUpdatesRecursive(
|
||||||
ReactShadowNode cssNode,
|
ReactShadowNode cssNode,
|
||||||
float absoluteX,
|
float absoluteX,
|
||||||
float absoluteY,
|
float absoluteY,
|
||||||
|
|
|
@ -440,7 +440,7 @@ public class UIViewOperationQueue {
|
||||||
|
|
||||||
private @Nullable NotThreadSafeViewHierarchyUpdateDebugListener mViewHierarchyUpdateDebugListener;
|
private @Nullable NotThreadSafeViewHierarchyUpdateDebugListener mViewHierarchyUpdateDebugListener;
|
||||||
|
|
||||||
protected UIViewOperationQueue(
|
public UIViewOperationQueue(
|
||||||
ReactApplicationContext reactContext,
|
ReactApplicationContext reactContext,
|
||||||
NativeViewHierarchyManager nativeViewHierarchyManager) {
|
NativeViewHierarchyManager nativeViewHierarchyManager) {
|
||||||
mNativeViewHierarchyManager = nativeViewHierarchyManager;
|
mNativeViewHierarchyManager = nativeViewHierarchyManager;
|
||||||
|
|
Loading…
Reference in New Issue