From 6aed5635cd7346ef31ef3f70661e0feed79d0b67 Mon Sep 17 00:00:00 2001 From: Matt Carroll Date: Tue, 11 Jun 2019 15:47:04 -0700 Subject: [PATCH] Expose a hasRenderedFirstFrame() method in FlutterView (#34275). (flutter/engine#9285) --- .../embedding/android/FlutterView.java | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/engine/src/flutter/shell/platform/android/io/flutter/embedding/android/FlutterView.java b/engine/src/flutter/shell/platform/android/io/flutter/embedding/android/FlutterView.java index 37986439e41..46eb7182bce 100644 --- a/engine/src/flutter/shell/platform/android/io/flutter/embedding/android/FlutterView.java +++ b/engine/src/flutter/shell/platform/android/io/flutter/embedding/android/FlutterView.java @@ -68,6 +68,7 @@ public class FlutterView extends FrameLayout { // Internal view hierarchy references. @Nullable private FlutterRenderer.RenderSurface renderSurface; + private boolean didRenderFirstFrame; // Connections to a Flutter execution context. @Nullable @@ -97,6 +98,13 @@ public class FlutterView extends FrameLayout { } }; + private final OnFirstFrameRenderedListener onFirstFrameRenderedListener = new OnFirstFrameRenderedListener() { + @Override + public void onFirstFrameRendered() { + didRenderFirstFrame = true; + } + }; + /** * Constructs a {@code FlutterView} programmatically, without any XML attributes. *

@@ -171,11 +179,34 @@ public class FlutterView extends FrameLayout { break; } + // Register a listener for the first frame render event to set didRenderFirstFrame. + renderSurface.addOnFirstFrameRenderedListener(onFirstFrameRenderedListener); + // FlutterView needs to be focusable so that the InputMethodManager can interact with it. setFocusable(true); setFocusableInTouchMode(true); } + /** + * Returns true if an attached {@link FlutterEngine} has rendered at least 1 frame to this + * {@code FlutterView}. + *

+ * Returns false if no {@link FlutterEngine} is attached. + *

+ * This flag is specific to a given {@link FlutterEngine}. The following hypothetical timeline + * demonstrates how this flag changes over time. + *

    + *
  1. {@code flutterEngineA} is attached to this {@code FlutterView}: returns false
  2. + *
  3. {@code flutterEngineA} renders its first frame to this {@code FlutterView}: returns true
  4. + *
  5. {@code flutterEngineA} is detached from this {@code FlutterView}: returns false
  6. + *
  7. {@code flutterEngineB} is attached to this {@code FlutterView}: returns false
  8. + *
  9. {@code flutterEngineB} renders its first frame to this {@code FlutterView}: returns true
  10. + *
+ */ + public boolean hasRenderedFirstFrame() { + return didRenderFirstFrame; + } + /** * Adds the given {@code listener} to this {@code FlutterView}, to be notified upon Flutter's * first rendered frame. @@ -471,6 +502,7 @@ public class FlutterView extends FrameLayout { this.flutterEngine = flutterEngine; // Instruct our FlutterRenderer that we are now its designated RenderSurface. + didRenderFirstFrame = false; this.flutterEngine.getRenderer().attachToRenderSurface(renderSurface); // Initialize various components that know how to process Android View I/O @@ -536,6 +568,7 @@ public class FlutterView extends FrameLayout { textInputPlugin.getInputMethodManager().restartInput(this); // Instruct our FlutterRenderer that we are no longer interested in being its RenderSurface. + didRenderFirstFrame = false; flutterEngine.getRenderer().detachFromRenderSurface(); flutterEngine = null;