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
This commit is contained in:
Joshua Gross
2020-06-19 20:25:40 -07:00
committed by Facebook GitHub Bot
parent e6d7f4a153
commit 304c5d54ec
@@ -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<Integer, ViewState> 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, " <ViewGroup tag=" + parentTag + ">");
for (int i = 0; i < parent.getChildCount(); i++) {
FLog.e(
TAG,
" <View tag="
+ parent.getChildAt(i).getId()
+ " toString="
+ parent.getChildAt(i).toString()
+ ">");
}
FLog.e(TAG, " </ViewGroup tag=" + parentTag + ">");
}
/**
* 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<ViewGroup> 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