From 304c5d54ec48c314524e089e989fbfdacca2c5c1 Mon Sep 17 00:00:00 2001 From: Joshua Gross Date: Fri, 19 Jun 2020 20:25:40 -0700 Subject: [PATCH] MountingManager debug tool: show view hierarchies before and after remove/insert operations Summary: This is a useful debugging tool that will not be compiled by default, and we have some protection to only compile it in Debug builds so it's less likely to accidentally slip into production. This has been useful for debugging C++ LayoutAnimations, since Remove/Insert mutations are delayed and fiddled around with a little. Changelog: [Internal] Reviewed By: mdvacca Differential Revision: D22148853 fbshipit-source-id: 05609507cdf06b73fd3edf5cf7bc95e124ff1135 --- .../fabric/mounting/MountingManager.java | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountingManager.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountingManager.java index 2f7f893b384..b845b335fd8 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountingManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountingManager.java @@ -28,6 +28,7 @@ import com.facebook.react.bridge.ReadableNativeMap; import com.facebook.react.bridge.RetryableMountingLayerException; import com.facebook.react.bridge.SoftAssertions; import com.facebook.react.bridge.UiThreadUtil; +import com.facebook.react.common.build.ReactBuildConfig; import com.facebook.react.fabric.FabricUIManager; import com.facebook.react.fabric.events.EventEmitterWrapper; import com.facebook.react.fabric.mounting.mountitems.MountItem; @@ -50,6 +51,7 @@ import java.util.concurrent.ConcurrentHashMap; */ public class MountingManager { public static final String TAG = MountingManager.class.getSimpleName(); + private static final boolean SHOW_CHANGED_VIEW_HIERARCHIES = ReactBuildConfig.DEBUG && false; @NonNull private final ConcurrentHashMap mTagToViewState; @NonNull private final JSResponderHandler mJSResponderHandler = new JSResponderHandler(); @@ -61,6 +63,21 @@ public class MountingManager { mViewManagerRegistry = viewManagerRegistry; } + private static void logViewHierarchy(ViewGroup parent) { + int parentTag = parent.getId(); + FLog.e(TAG, " "); + for (int i = 0; i < parent.getChildCount(); i++) { + FLog.e( + TAG, + " "); + } + FLog.e(TAG, " "); + } + /** * This mutates the rootView, which is an Android View, so this should only be called on the UI * thread. @@ -132,7 +149,20 @@ public class MountingManager { throw new IllegalStateException( "Unable to find view for viewState " + viewState + " and tag " + tag); } + + // Display children before inserting + if (SHOW_CHANGED_VIEW_HIERARCHIES) { + FLog.e(TAG, "addViewAt: [" + tag + "] -> [" + parentTag + "] idx: " + index + " BEFORE"); + logViewHierarchy(parentView); + } + getViewGroupManager(parentViewState).addView(parentView, view, index); + + // Display children after inserting + if (SHOW_CHANGED_VIEW_HIERARCHIES) { + FLog.e(TAG, "addViewAt: [" + tag + "] -> [" + parentTag + "] idx: " + index + " AFTER"); + logViewHierarchy(parentView); + } } private @NonNull ViewState getViewState(int tag) { @@ -242,6 +272,12 @@ public class MountingManager { throw new IllegalStateException("Unable to find view for tag " + parentTag); } + if (SHOW_CHANGED_VIEW_HIERARCHIES) { + // Display children before deleting any + FLog.e(TAG, "removeViewAt: [" + tag + "] -> [" + parentTag + "] idx: " + index + " BEFORE"); + logViewHierarchy(parentView); + } + ViewGroupManager viewGroupManager = getViewGroupManager(viewState); // Verify that the view we're about to remove has the same tag we expect @@ -290,6 +326,12 @@ public class MountingManager { + " children in parent. Warning: childCount may be incorrect!", e); } + + // Display children after deleting any + if (SHOW_CHANGED_VIEW_HIERARCHIES) { + FLog.e(TAG, "removeViewAt: [" + parentTag + "] idx: " + index + " AFTER"); + logViewHierarchy(parentView); + } } @UiThread