From 0d7a0dc9976b179fab8ee1b77c9b9faf85f7d828 Mon Sep 17 00:00:00 2001 From: Luna Wei Date: Mon, 13 May 2019 10:57:33 -0700 Subject: [PATCH] Add log to view that is being dropped Summary: We are getting errors where views are being dropped twice. This is following from logic that viewManagers are only removed from `mTagsToViewManagers` from `dropView`. This log will hopefully identify if we are getting improper operations because we shouldn't be re-using tags Reviewed By: mdvacca Differential Revision: D15152869 fbshipit-source-id: 914ee9c1772fa066adefde0753075ecba6377a0c --- .../react/config/ReactFeatureFlags.java | 6 ++++++ .../uimanager/NativeViewHierarchyManager.java | 18 +++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java b/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java index 1171fa909c..94ae2364c6 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java +++ b/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java @@ -37,4 +37,10 @@ public class ReactFeatureFlags { * C++ CatalystInstanceImpl */ public static boolean useTurboModules = false; + + /** + * Log tags of when a view deleted on the native side + * {@link com.facebook.react.uimanager.NativeViewHierarchyManager dropView} + */ + public static boolean logDroppedViews = false; } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyManager.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyManager.java index cec15412ed..724dd8e81d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyManager.java @@ -28,11 +28,13 @@ import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.SoftAssertions; import com.facebook.react.bridge.UiThreadUtil; +import com.facebook.react.config.ReactFeatureFlags; import com.facebook.react.touch.JSResponderHandler; import com.facebook.react.uimanager.layoutanimation.LayoutAnimationController; import com.facebook.react.uimanager.layoutanimation.LayoutAnimationListener; import com.facebook.systrace.Systrace; import com.facebook.systrace.SystraceMessage; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; import javax.annotation.Nullable; @@ -73,9 +75,11 @@ public class NativeViewHierarchyManager { private final RootViewManager mRootViewManager; private final LayoutAnimationController mLayoutAnimator = new LayoutAnimationController(); private final Map mTagsToPendingIndicesToDelete = new HashMap<>(); + private final int[] mDroppedViewArray = new int[100]; private boolean mLayoutAnimationEnabled; private PopupMenu mPopupMenu; + private int mDroppedViewIndex = 0; public NativeViewHierarchyManager(ViewManagerRegistry viewManagers) { this(viewManagers, new RootViewManager()); @@ -101,7 +105,11 @@ public class NativeViewHierarchyManager { public synchronized final ViewManager resolveViewManager(int tag) { ViewManager viewManager = mTagsToViewManagers.get(tag); if (viewManager == null) { - throw new IllegalViewOperationException("ViewManager for tag " + tag + " could not be found"); + boolean alreadyDropped = Arrays.asList(mDroppedViewArray).contains(tag); + throw new IllegalViewOperationException("ViewManager for tag " + + tag + " could not be found.\n View already dropped? " + + alreadyDropped + ".\nLast index "+ mDroppedViewIndex + " in last 100 views" + + mDroppedViewArray.toString()); } return viewManager; } @@ -587,6 +595,11 @@ public class NativeViewHierarchyManager { view.setId(tag); } + private void cacheDroppedTag(int tag) { + mDroppedViewArray[mDroppedViewIndex] = tag; + mDroppedViewIndex = (mDroppedViewIndex + 1) % 100; + } + /** * Releases all references to given native View. */ @@ -596,6 +609,9 @@ public class NativeViewHierarchyManager { // Ignore this drop operation when view is null. return; } + if (ReactFeatureFlags.logDroppedViews) { + cacheDroppedTag(view.getId()); + } if (mTagsToViewManagers.get(view.getId()) == null) { // This view has already been dropped (likely due to a threading issue caused by async js // execution). Ignore this drop operation.