From c06432da47bda910bbd87171a84ec7055128800b Mon Sep 17 00:00:00 2001 From: amirh Date: Mon, 20 Aug 2018 12:13:26 -0700 Subject: [PATCH] Delay the removal of the onDrawListener. (#6052) In Android O removing the ViewTreeObserver.onDrawListener from the listener call crashes. Instead we post a runnable to remove it. --- .../platform/VirtualDisplayController.java | 37 +++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/shell/platform/android/io/flutter/plugin/platform/VirtualDisplayController.java b/shell/platform/android/io/flutter/plugin/platform/VirtualDisplayController.java index 2e062f8c2..656246cf5 100644 --- a/shell/platform/android/io/flutter/plugin/platform/VirtualDisplayController.java +++ b/shell/platform/android/io/flutter/plugin/platform/VirtualDisplayController.java @@ -98,9 +98,9 @@ class VirtualDisplayController { embeddedView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { @Override public void onViewAttachedToWindow(View v) { - embeddedView.getViewTreeObserver().addOnDrawListener(new ViewTreeObserver.OnDrawListener() { + OneTimeOnDrawListener.schedule(embeddedView, new Runnable() { @Override - public void onDraw() { + public void run() { // We need some delay here until the frame propagates through the vd surface to to the texture, // 128ms was picked pretty arbitrarily based on trial and error. // As long as we invoke the runnable after a new frame is available we avoid the scaling jank @@ -108,7 +108,6 @@ class VirtualDisplayController { // We should ideally run onNewSizeFrameAvailable ASAP to make the embedded view more responsive // following a resize. embeddedView.postDelayed(onNewSizeFrameAvailable, 128); - embeddedView.getViewTreeObserver().removeOnDrawListener(this); } }); embeddedView.removeOnAttachStateChangeListener(this); @@ -135,4 +134,36 @@ class VirtualDisplayController { PlatformView platformView = mPresentation.getView(); return platformView.getView(); } + + @TargetApi(Build.VERSION_CODES.JELLY_BEAN) + static class OneTimeOnDrawListener implements ViewTreeObserver.OnDrawListener { + static void schedule(View view, Runnable runnable) { + OneTimeOnDrawListener listener = new OneTimeOnDrawListener(view, runnable); + view.getViewTreeObserver().addOnDrawListener(listener); + } + + final View mView; + Runnable mOnDrawRunnable; + + OneTimeOnDrawListener(View view, Runnable onDrawRunnable) { + this.mView = view; + this.mOnDrawRunnable = onDrawRunnable; + } + + @Override + public void onDraw() { + if (mOnDrawRunnable == null) { + return; + } + mOnDrawRunnable.run(); + mOnDrawRunnable = null; + mView.post(new Runnable() { + @Override + public void run() { + mView.getViewTreeObserver().removeOnDrawListener(OneTimeOnDrawListener.this); + } + }); + } + } } + -- GitLab