-
Notifications
You must be signed in to change notification settings - Fork 6k
Wait before switching surfaces #20100
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -949,13 +949,22 @@ public void detachFromFlutterEngine() { | |
flutterEngine = null; | ||
} | ||
|
||
@VisibleForTesting | ||
@NonNull | ||
public FlutterImageView createImageView() { | ||
return new FlutterImageView( | ||
getContext(), getWidth(), getHeight(), FlutterImageView.SurfaceKind.background); | ||
} | ||
|
||
/** | ||
* Converts the current render surface to a {@link FlutterImageView} if it's not one already. | ||
* Otherwise, it resizes the {@link FlutterImageView} based on the current view size. | ||
*/ | ||
public void convertToImageView() { | ||
renderSurface.pause(); | ||
|
||
if (flutterImageView == null) { | ||
flutterImageView = | ||
new FlutterImageView( | ||
getContext(), getWidth(), getHeight(), FlutterImageView.SurfaceKind.background); | ||
flutterImageView = createImageView(); | ||
addView(flutterImageView); | ||
} else { | ||
flutterImageView.resizeIfNeeded(getWidth(), getHeight()); | ||
|
@@ -969,10 +978,13 @@ public void convertToImageView() { | |
} | ||
|
||
/** | ||
* If the surface is rendered by a {@code FlutterImageView}. Then, calling this method will stop | ||
* rendering to a {@code FlutterImageView}, and use the previous surface instead. | ||
* If the surface is rendered by a {@link FlutterImageView}, then calling this method will stop | ||
* rendering to a {@link FlutterImageView}, and render on the previous surface instead. | ||
* | ||
* @param onDone a callback called when Flutter UI is rendered on the previous surface. Use this | ||
* callback to perform cleanups. For example, destroy overlay surfaces. | ||
*/ | ||
public void revertImageView() { | ||
public void revertImageView(@NonNull Runnable onDone) { | ||
if (flutterImageView == null) { | ||
Log.v(TAG, "Tried to revert the image view, but no image view is used."); | ||
return; | ||
|
@@ -981,12 +993,39 @@ public void revertImageView() { | |
Log.v(TAG, "Tried to revert the image view, but no previous surface was used."); | ||
return; | ||
} | ||
flutterImageView.detachFromRenderer(); | ||
renderSurface = previousRenderSurface; | ||
previousRenderSurface = null; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The fact that there's a single instance variable for the previous surface seems weird... can you render an image view over an image view? should we keep a stack of surfaces? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ack.
No. Only |
||
if (flutterEngine != null) { | ||
renderSurface.attachToRenderer(flutterEngine.getRenderer()); | ||
if (flutterEngine == null) { | ||
flutterImageView.detachFromRenderer(); | ||
onDone.run(); | ||
return; | ||
} | ||
final FlutterRenderer renderer = flutterEngine.getRenderer(); | ||
if (renderer == null) { | ||
flutterImageView.detachFromRenderer(); | ||
onDone.run(); | ||
return; | ||
} | ||
// Start rendering on the previous surface. | ||
// This surface is typically `FlutterSurfaceView` or `FlutterTextureView`. | ||
renderSurface.attachToRenderer(renderer); | ||
|
||
// Install a Flutter UI listener to wait until the first frame is rendered | ||
// in the new surface to call the `onDone` callback. | ||
renderer.addIsDisplayingFlutterUiListener( | ||
new FlutterUiDisplayListener() { | ||
@Override | ||
public void onFlutterUiDisplayed() { | ||
renderer.removeIsDisplayingFlutterUiListener(this); | ||
onDone.run(); | ||
flutterImageView.detachFromRenderer(); | ||
} | ||
|
||
@Override | ||
public void onFlutterUiNoLongerDisplayed() { | ||
// no-op | ||
} | ||
}); | ||
} | ||
|
||
public void attachOverlaySurfaceToRender(FlutterImageView view) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -90,7 +90,7 @@ | |
* | ||
* <p>To invoke a native method that is not associated with a platform view, invoke it statically: | ||
* | ||
* <p>{@code bool enabled = FlutterJNI.nativeGetIsSoftwareRenderingEnabled(); } | ||
* <p>{@code bool enabled = FlutterJNI.getIsSoftwareRenderingEnabled(); } | ||
*/ | ||
@Keep | ||
public class FlutterJNI { | ||
|
@@ -120,9 +120,13 @@ public static native void nativeInit( | |
*/ | ||
public static native void nativePrefetchDefaultFontManager(); | ||
|
||
// TODO(mattcarroll): add javadocs | ||
private native boolean nativeGetIsSoftwareRenderingEnabled(); | ||
|
||
@UiThread | ||
public native boolean nativeGetIsSoftwareRenderingEnabled(); | ||
// TODO(mattcarroll): add javadocs | ||
public boolean getIsSoftwareRenderingEnabled() { | ||
return nativeGetIsSoftwareRenderingEnabled(); | ||
} | ||
|
||
@Nullable | ||
// TODO(mattcarroll): add javadocs | ||
|
@@ -212,7 +216,12 @@ public boolean isAttached() { | |
public void attachToNative(boolean isBackgroundView) { | ||
ensureRunningOnMainThread(); | ||
ensureNotAttachedToNative(); | ||
nativePlatformViewId = nativeAttach(this, isBackgroundView); | ||
nativePlatformViewId = performNativeAttach(this, isBackgroundView); | ||
} | ||
|
||
@VisibleForTesting | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can this be package private? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unfortunately, it can't because |
||
public long performNativeAttach(@NonNull FlutterJNI flutterJNI, boolean isBackgroundView) { | ||
return nativeAttach(flutterJNI, isBackgroundView); | ||
} | ||
|
||
private native long nativeAttach(@NonNull FlutterJNI flutterJNI, boolean isBackgroundView); | ||
|
@@ -279,7 +288,7 @@ public void removeIsDisplayingFlutterUiListener(@NonNull FlutterUiDisplayListene | |
@SuppressWarnings("unused") | ||
@VisibleForTesting | ||
@UiThread | ||
void onFirstFrame() { | ||
public void onFirstFrame() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can this be package private? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto |
||
ensureRunningOnMainThread(); | ||
|
||
for (FlutterUiDisplayListener listener : flutterUiDisplayListeners) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are the tests in the same package (can this be package private)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
different packages unfortunately.
io.flutter.embedding.android
vsio.flutter.plugin.platform