Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 14af034

Browse files
authored
Complete the AndroidView resize call only after a new frame is ready. (#5968)
This allows the framework to know that a frame with the resized view is ready and to behave deterministically to workaround the jank issue described in flutter/flutter/19572
1 parent 08b660e commit 14af034

2 files changed

Lines changed: 38 additions & 6 deletions

File tree

shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ private void disposePlatformView(MethodCall call, MethodChannel.Result result) {
171171
result.success(null);
172172
}
173173

174-
private void resizePlatformView(MethodCall call, MethodChannel.Result result) {
174+
private void resizePlatformView(MethodCall call, final MethodChannel.Result result) {
175175
Map<String, Object> args = call.arguments();
176176
int id = (int) args.get("id");
177177
double width = (double) args.get("width");
@@ -188,9 +188,14 @@ private void resizePlatformView(MethodCall call, MethodChannel.Result result) {
188188
}
189189
vdController.resize(
190190
toPhysicalPixels(width),
191-
toPhysicalPixels(height)
191+
toPhysicalPixels(height),
192+
new Runnable() {
193+
@Override
194+
public void run() {
195+
result.success(null);
196+
}
197+
}
192198
);
193-
result.success(null);
194199
}
195200

196201
private void onTouch(MethodCall call, MethodChannel.Result result) {

shell/platform/android/io/flutter/plugin/platform/VirtualDisplayController.java

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import android.os.Build;
1313
import android.view.Surface;
1414
import android.view.View;
15+
import android.view.ViewTreeObserver;
1516

1617
@TargetApi(Build.VERSION_CODES.KITKAT_WATCH)
1718
class VirtualDisplayController {
@@ -70,9 +71,8 @@ private VirtualDisplayController(
7071
mPresentation.show();
7172
}
7273

73-
public void resize(int width, int height) {
74-
PlatformView view = mPresentation.detachView();
75-
mPresentation.hide();
74+
public void resize(final int width, final int height, final Runnable onNewSizeFrameAvailable) {
75+
final PlatformView view = mPresentation.detachView();
7676
// We detach the surface to prevent it being destroyed when releasing the vd.
7777
//
7878
// setSurface is only available starting API 20. We could support API 19 by re-creating a new
@@ -91,6 +91,33 @@ public void resize(int width, int height) {
9191
mSurface,
9292
0
9393
);
94+
95+
final View embeddedView = getView();
96+
// There's a bug in Android version older than O where view tree observer onDrawListeners don't get properly
97+
// merged when attaching to window, as a workaround we register the on draw listener after the view is attached.
98+
embeddedView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
99+
@Override
100+
public void onViewAttachedToWindow(View v) {
101+
embeddedView.getViewTreeObserver().addOnDrawListener(new ViewTreeObserver.OnDrawListener() {
102+
@Override
103+
public void onDraw() {
104+
// We need some delay here until the frame propagates through the vd surface to to the texture,
105+
// 128ms was picked pretty arbitrarily based on trial and error.
106+
// As long as we invoke the runnable after a new frame is available we avoid the scaling jank
107+
// described in: https://github.com/flutter/flutter/issues/19572
108+
// We should ideally run onNewSizeFrameAvailable ASAP to make the embedded view more responsive
109+
// following a resize.
110+
embeddedView.postDelayed(onNewSizeFrameAvailable, 128);
111+
embeddedView.getViewTreeObserver().removeOnDrawListener(this);
112+
}
113+
});
114+
embeddedView.removeOnAttachStateChangeListener(this);
115+
}
116+
117+
@Override
118+
public void onViewDetachedFromWindow(View v) {}
119+
});
120+
94121
mPresentation = new SingleViewPresentation(mContext, mVirtualDisplay.getDisplay(), view);
95122
mPresentation.show();
96123
}

0 commit comments

Comments
 (0)