diff --git a/shell/platform/android/io/flutter/embedding/engine/renderer/FlutterRenderer.java b/shell/platform/android/io/flutter/embedding/engine/renderer/FlutterRenderer.java index e9559b4383b08..1eac92546a659 100644 --- a/shell/platform/android/io/flutter/embedding/engine/renderer/FlutterRenderer.java +++ b/shell/platform/android/io/flutter/embedding/engine/renderer/FlutterRenderer.java @@ -370,19 +370,20 @@ public void surfaceChanged(int width, int height) { * android.view.TextureView.SurfaceTextureListener} */ public void stopRenderingToSurface() { - flutterJNI.onSurfaceDestroyed(); - - surface = null; + if (surface != null) { + flutterJNI.onSurfaceDestroyed(); + + // TODO(mattcarroll): the source of truth for this call should be FlutterJNI, which is where + // the call to onFlutterUiDisplayed() comes from. However, no such native callback exists yet, + // so until the engine and FlutterJNI are configured to call us back when rendering stops, + // we will manually monitor that change here. + if (isDisplayingFlutterUi) { + flutterUiDisplayListener.onFlutterUiNoLongerDisplayed(); + } - // TODO(mattcarroll): the source of truth for this call should be FlutterJNI, which is where - // the call to onFlutterUiDisplayed() comes from. However, no such native callback exists yet, - // so until the engine and FlutterJNI are configured to call us back when rendering stops, - // we will manually monitor that change here. - if (isDisplayingFlutterUi) { - flutterUiDisplayListener.onFlutterUiNoLongerDisplayed(); + isDisplayingFlutterUi = false; + surface = null; } - - isDisplayingFlutterUi = false; } /** diff --git a/shell/platform/android/test/io/flutter/embedding/engine/renderer/FlutterRendererTest.java b/shell/platform/android/test/io/flutter/embedding/engine/renderer/FlutterRendererTest.java index e7b0d0daa1c03..b1f4d3f76fd5f 100644 --- a/shell/platform/android/test/io/flutter/embedding/engine/renderer/FlutterRendererTest.java +++ b/shell/platform/android/test/io/flutter/embedding/engine/renderer/FlutterRendererTest.java @@ -393,4 +393,20 @@ public void onTrimMemory(int level) { // Verify behavior under test. assertEquals(1, invocationCount.get()); } + + @Test + public void itDoesDispatchSurfaceDestructionNotificationOnlyOnce() { + // Setup the test. + FlutterRenderer flutterRenderer = new FlutterRenderer(fakeFlutterJNI); + + flutterRenderer.startRenderingToSurface(fakeSurface, /*keepCurrentSurface=*/ false); + + // Execute the behavior under test. + // Simulate calling |FlutterRenderer#stopRenderingToSurface| twice with different code paths. + flutterRenderer.stopRenderingToSurface(); + flutterRenderer.stopRenderingToSurface(); + + // Verify behavior under test. + verify(fakeFlutterJNI, times(1)).onSurfaceDestroyed(); + } }