From 1fde677cfc8abc1b0c300077da5286810b51b924 Mon Sep 17 00:00:00 2001 From: Listen Date: Tue, 15 Jan 2019 20:42:13 -0800 Subject: [PATCH] Remove duplicated `OnGlobalLayoutListener` to improve performance (#22849) Summary: We are writing a native navigation library. When there are more than a dozen `ReactRootView` in the application, the application will be very stuck. It doesn't improve much, even if we remove the invisible ReactRootView from the View hierarchy temporarily. After debugging, we found that we were not able to remove `OnGlobalLayoutListener` in `onDetachedFromWindow` because this listener was added twice. One is in `onAttachedToWindow` and the other is in `attachToReactInstanceManager`. We added the following code by inheriting ReactRootView. ```java Override protected void onAttachedToWindow() { try { Method method = ReactRootView.class.getDeclaredMethod("getCustomGlobalLayoutListener"); method.setAccessible(true); // remove duplicated GlobalLayoutListener if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { getViewTreeObserver().removeOnGlobalLayoutListener((ViewTreeObserver.OnGlobalLayoutListener) method.invoke(this)); } else { getViewTreeObserver().removeGlobalOnLayoutListener((ViewTreeObserver.OnGlobalLayoutListener) method.invoke(this)); } } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } super.onAttachedToWindow(); } ``` It turns out that there is no pressure even if opening hundreds of pages that contain ReactRootView (remove ReactRootView from the View hierarchy temporarily in the invisible pages). Changelog: ---------- [Android] [Fixed] - Remove duplicated `OnGlobalLayoutListener` to improve performance. Pull Request resolved: https://github.com/facebook/react-native/pull/22849 Differential Revision: D13682818 Pulled By: hramos fbshipit-source-id: 1f1bc8cd5fc4e01a1bc2f2a4784822b4eae92fdc --- .../java/com/facebook/react/ReactRootView.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java b/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java index 8441065aa95..0a98d47bc2d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java @@ -308,6 +308,7 @@ public class ReactRootView extends SizeMonitoringFrameLayout protected void onAttachedToWindow() { super.onAttachedToWindow(); if (mIsAttachedToInstance) { + removeOnGlobalLayoutListener(); getViewTreeObserver().addOnGlobalLayoutListener(getCustomGlobalLayoutListener()); } } @@ -316,11 +317,15 @@ public class ReactRootView extends SizeMonitoringFrameLayout protected void onDetachedFromWindow() { super.onDetachedFromWindow(); if (mIsAttachedToInstance) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - getViewTreeObserver().removeOnGlobalLayoutListener(getCustomGlobalLayoutListener()); - } else { - getViewTreeObserver().removeGlobalOnLayoutListener(getCustomGlobalLayoutListener()); - } + removeOnGlobalLayoutListener(); + } + } + + private void removeOnGlobalLayoutListener() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + getViewTreeObserver().removeOnGlobalLayoutListener(getCustomGlobalLayoutListener()); + } else { + getViewTreeObserver().removeGlobalOnLayoutListener(getCustomGlobalLayoutListener()); } }