From 20b09e4c45b7d9fd15d433a106a2cd8086d7478c Mon Sep 17 00:00:00 2001 From: Guilherme Iscaro Date: Mon, 29 Apr 2019 09:25:18 -0700 Subject: [PATCH] The ART '' becomes invisible in Android (#22624) Summary: Hello Everyone, this series of commits helps to fix problems related to ART on Android. The main problem in here is that the ART components would disappear if the user turns off the screen and then turn it on again. It's important to note that this behaviour only occurs after Android N (7.1 or higher). Pull Request resolved: https://github.com/facebook/react-native/pull/22624 Differential Revision: D15122573 Pulled By: cpojer fbshipit-source-id: e7fb8b9280b4c52562e3d0c1a89759d4d31cd53d --- .../views/art/ARTSurfaceViewManager.java | 3 +- .../views/art/ARTSurfaceViewShadowNode.java | 56 ++++++++++++++++--- 2 files changed, 51 insertions(+), 8 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTSurfaceViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTSurfaceViewManager.java index 351e9628431..e7cc4c652f6 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTSurfaceViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTSurfaceViewManager.java @@ -60,7 +60,8 @@ public class ARTSurfaceViewManager extends @Override public void updateExtraData(ARTSurfaceView root, Object extraData) { - root.setSurfaceTextureListener((ARTSurfaceViewShadowNode) extraData); + ARTSurfaceViewShadowNode shadowNode = (ARTSurfaceViewShadowNode) extraData; + shadowNode.setupSurfaceTextureListener(root); } @Override diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTSurfaceViewShadowNode.java b/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTSurfaceViewShadowNode.java index 7e20931a8f7..b154c0c4d05 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTSurfaceViewShadowNode.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTSurfaceViewShadowNode.java @@ -16,6 +16,7 @@ import android.view.Surface; import android.graphics.PorterDuff; import android.graphics.SurfaceTexture; import android.view.TextureView; +import android.os.Build; import com.facebook.common.logging.FLog; import com.facebook.react.common.ReactConstants; @@ -23,13 +24,15 @@ import com.facebook.react.uimanager.LayoutShadowNode; import com.facebook.react.uimanager.UIViewOperationQueue; import com.facebook.react.uimanager.ReactShadowNode; import com.facebook.react.uimanager.ViewProps; +import com.facebook.react.uimanager.ThemedReactContext; import com.facebook.react.uimanager.annotations.ReactProp; +import com.facebook.react.bridge.LifecycleEventListener; /** * Shadow node for ART virtual tree root - ARTSurfaceView */ public class ARTSurfaceViewShadowNode extends LayoutShadowNode - implements TextureView.SurfaceTextureListener { + implements TextureView.SurfaceTextureListener, LifecycleEventListener { private @Nullable Surface mSurface; @@ -54,11 +57,11 @@ public class ARTSurfaceViewShadowNode extends LayoutShadowNode @Override public void onCollectExtraUpdates(UIViewOperationQueue uiUpdater) { super.onCollectExtraUpdates(uiUpdater); - drawOutput(); + drawOutput(false); uiUpdater.enqueueUpdateExtraData(getReactTag(), this); } - private void drawOutput() { + private void drawOutput(boolean markAsUpdated) { if (mSurface == null || !mSurface.isValid()) { markChildrenUpdatesSeen(this); return; @@ -75,19 +78,31 @@ public class ARTSurfaceViewShadowNode extends LayoutShadowNode for (int i = 0; i < getChildCount(); i++) { ARTVirtualNode child = (ARTVirtualNode) getChildAt(i); child.draw(canvas, paint, 1f); - child.markUpdateSeen(); + if (markAsUpdated) { + child.markUpdated(); + } else { + child.markUpdateSeen(); + } } if (mSurface == null) { return; } - mSurface.unlockCanvasAndPost(canvas); } catch (IllegalArgumentException | IllegalStateException e) { FLog.e(ReactConstants.TAG, e.getClass().getSimpleName() + " in Surface.unlockCanvasAndPost"); } } + public void setupSurfaceTextureListener(ARTSurfaceView surfaceView) { + SurfaceTexture surface = surfaceView.getSurfaceTexture(); + surfaceView.setSurfaceTextureListener(this); + if (surface != null && mSurface == null) { + mSurface = new Surface(surface); + drawOutput(true); + } + } + private void markChildrenUpdatesSeen(ReactShadowNode shadowNode) { for (int i = 0; i < shadowNode.getChildCount(); i++) { ReactShadowNode child = shadowNode.getChildAt(i); @@ -96,15 +111,42 @@ public class ARTSurfaceViewShadowNode extends LayoutShadowNode } } + @Override + public void setThemedContext(ThemedReactContext themedContext) { + super.setThemedContext(themedContext); + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) { + themedContext.addLifecycleEventListener(this); + } + } + + @Override + public void dispose() { + super.dispose(); + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) { + getThemedContext().removeLifecycleEventListener(this); + } + } + + @Override + public void onHostResume() { + drawOutput(false); + } + + @Override + public void onHostPause() {} + + @Override + public void onHostDestroy() {} + @Override public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { mSurface = new Surface(surface); - drawOutput(); + drawOutput(false); } @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { - surface.release(); + mSurface.release(); mSurface = null; return true; }