diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index e02a6409acf08..9494862af2ea8 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1483,6 +1483,7 @@ FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/Platfor FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/SingleViewPresentation.java FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/VirtualDisplayController.java +FILE: ../../../flutter/shell/platform/android/io/flutter/util/HandlerCompat.java FILE: ../../../flutter/shell/platform/android/io/flutter/util/PathUtils.java FILE: ../../../flutter/shell/platform/android/io/flutter/util/Preconditions.java FILE: ../../../flutter/shell/platform/android/io/flutter/util/Predicate.java diff --git a/shell/platform/android/BUILD.gn b/shell/platform/android/BUILD.gn index 84827f4610e77..c727e4f34371f 100644 --- a/shell/platform/android/BUILD.gn +++ b/shell/platform/android/BUILD.gn @@ -288,6 +288,7 @@ android_java_sources = [ "io/flutter/plugin/platform/PlatformViewsController.java", "io/flutter/plugin/platform/SingleViewPresentation.java", "io/flutter/plugin/platform/VirtualDisplayController.java", + "io/flutter/util/HandlerCompat.java", "io/flutter/util/PathUtils.java", "io/flutter/util/Preconditions.java", "io/flutter/util/Predicate.java", diff --git a/shell/platform/android/io/flutter/embedding/engine/dart/PlatformTaskQueue.java b/shell/platform/android/io/flutter/embedding/engine/dart/PlatformTaskQueue.java index e90ab89e62223..82d022a43907d 100644 --- a/shell/platform/android/io/flutter/embedding/engine/dart/PlatformTaskQueue.java +++ b/shell/platform/android/io/flutter/embedding/engine/dart/PlatformTaskQueue.java @@ -7,10 +7,13 @@ import android.os.Handler; import android.os.Looper; import androidx.annotation.NonNull; +import io.flutter.util.HandlerCompat; /** A BinaryMessenger.TaskQueue that posts to the platform thread (aka main thread). */ public class PlatformTaskQueue implements DartMessenger.DartMessengerTaskQueue { - @NonNull private final Handler handler = new Handler(Looper.getMainLooper()); + // Use an async handler because the default is subject to vsync synchronization and can result + // in delays when dispatching tasks. + @NonNull private final Handler handler = HandlerCompat.createAsyncHandler(Looper.getMainLooper()); @Override public void dispatch(@NonNull Runnable runnable) { diff --git a/shell/platform/android/io/flutter/embedding/engine/loader/FlutterLoader.java b/shell/platform/android/io/flutter/embedding/engine/loader/FlutterLoader.java index 629984600d758..b09be89e4b57f 100644 --- a/shell/platform/android/io/flutter/embedding/engine/loader/FlutterLoader.java +++ b/shell/platform/android/io/flutter/embedding/engine/loader/FlutterLoader.java @@ -23,6 +23,7 @@ import io.flutter.FlutterInjector; import io.flutter.Log; import io.flutter.embedding.engine.FlutterJNI; +import io.flutter.util.HandlerCompat; import io.flutter.util.PathUtils; import io.flutter.util.TraceSection; import io.flutter.view.VsyncWaiter; @@ -385,7 +386,7 @@ public void ensureInitializationCompleteAsync( Log.e(TAG, "Flutter initialization failed.", e); throw new RuntimeException(e); } - new Handler(Looper.getMainLooper()) + HandlerCompat.createAsyncHandler(Looper.getMainLooper()) .post( () -> { ensureInitializationComplete(applicationContext.getApplicationContext(), args); diff --git a/shell/platform/android/io/flutter/util/HandlerCompat.java b/shell/platform/android/io/flutter/util/HandlerCompat.java new file mode 100644 index 0000000000000..de391419a9abd --- /dev/null +++ b/shell/platform/android/io/flutter/util/HandlerCompat.java @@ -0,0 +1,35 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package io.flutter.util; + +import android.os.Build; +import android.os.Handler; +import android.os.Looper; + +/** Compatability wrapper over {@link Handler}. */ +public final class HandlerCompat { + /** + * Create a new Handler whose posted messages and runnables are not subject to synchronization + * barriers such as display vsync. + * + *
Messages sent to an async handler are guaranteed to be ordered with respect to one another, + * but not necessarily with respect to messages from other Handlers. Compatibility behavior: + * + *