diff --git a/engine/src/flutter/ci/licenses_golden/licenses_flutter b/engine/src/flutter/ci/licenses_golden/licenses_flutter index b12f2b1322a..b1f00b23a7e 100644 --- a/engine/src/flutter/ci/licenses_golden/licenses_flutter +++ b/engine/src/flutter/ci/licenses_golden/licenses_flutter @@ -593,7 +593,6 @@ FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/Flutt FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/SplashScreen.java FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/SplashScreenProvider.java FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java -FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngineAndroidLifecycle.java FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngineCache.java FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEnginePluginRegistry.java FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java diff --git a/engine/src/flutter/shell/platform/android/BUILD.gn b/engine/src/flutter/shell/platform/android/BUILD.gn index 7ba8969d5bd..ac7ffaed19a 100644 --- a/engine/src/flutter/shell/platform/android/BUILD.gn +++ b/engine/src/flutter/shell/platform/android/BUILD.gn @@ -141,7 +141,6 @@ android_java_sources = [ "io/flutter/embedding/android/SplashScreen.java", "io/flutter/embedding/android/SplashScreenProvider.java", "io/flutter/embedding/engine/FlutterEngine.java", - "io/flutter/embedding/engine/FlutterEngineAndroidLifecycle.java", "io/flutter/embedding/engine/FlutterEngineCache.java", "io/flutter/embedding/engine/FlutterEnginePluginRegistry.java", "io/flutter/embedding/engine/FlutterJNI.java", diff --git a/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java b/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java index 6a55007a323..515b15070ce 100644 --- a/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java +++ b/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java @@ -4,8 +4,6 @@ package io.flutter.embedding.engine; -import android.arch.lifecycle.Lifecycle; -import android.arch.lifecycle.LifecycleOwner; import android.content.Context; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -68,7 +66,7 @@ import io.flutter.plugin.platform.PlatformViewsController; * {@link DartExecutor} is run. Each Isolate is a self-contained Dart environment and cannot * communicate with each other except via Isolate ports. */ -public class FlutterEngine implements LifecycleOwner { +public class FlutterEngine { private static final String TAG = "FlutterEngine"; @NonNull @@ -79,8 +77,6 @@ public class FlutterEngine implements LifecycleOwner { private final DartExecutor dartExecutor; @NonNull private final FlutterEnginePluginRegistry pluginRegistry; - @NonNull - private final FlutterEngineAndroidLifecycle androidLifecycle; // System channels. @NonNull @@ -205,11 +201,9 @@ public class FlutterEngine implements LifecycleOwner { platformViewsController = new PlatformViewsController(); - androidLifecycle = new FlutterEngineAndroidLifecycle(this); this.pluginRegistry = new FlutterEnginePluginRegistry( context.getApplicationContext(), - this, - androidLifecycle + this ); } @@ -396,13 +390,6 @@ public class FlutterEngine implements LifecycleOwner { return pluginRegistry; } - // TODO(mattcarroll): determine if we really need to expose this from FlutterEngine vs making PluginBinding a LifecycleOwner - @NonNull - @Override - public Lifecycle getLifecycle() { - return androidLifecycle; - } - /** * Lifecycle callbacks for Flutter engine lifecycle events. */ diff --git a/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngineAndroidLifecycle.java b/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngineAndroidLifecycle.java deleted file mode 100644 index 0a33aca1de7..00000000000 --- a/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngineAndroidLifecycle.java +++ /dev/null @@ -1,131 +0,0 @@ -// 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.embedding.engine; - -import android.arch.lifecycle.DefaultLifecycleObserver; -import android.arch.lifecycle.Lifecycle; -import android.arch.lifecycle.LifecycleObserver; -import android.arch.lifecycle.LifecycleOwner; -import android.arch.lifecycle.LifecycleRegistry; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -/** - * Android {@link Lifecycle} that is owned by a {@link FlutterEngine}. - *
- * {@code FlutterEngineAndroidLifecycle} exists so that {@code FlutterPlugin}s can monitor Android - * lifecycle events. When the associated {@link FlutterEngine} is running in an {@code Activity}, - * that {@code Activity}'s {@link Lifecycle} can be set as the {@code backingLifecycle} of this - * class, allowing all Flutter plugins to receive the {@code Activity}'s lifecycle events. Likewise, - * when the associated {@link FlutterEngine} is running in a {@code Service}, that {@code Service}'s - * {@link Lifecycle} can be set as the {@code backingLifecycle}. - *
- * Sometimes a {@link FlutterEngine} exists in a non-lifecycle location, e.g., an {@code Application}, - * {@code ContentProvider}, or {@code BroadcastReceiver}. In these cases, this lifecycle reports - * itself in the {@link Lifecycle.State#CREATED} state. - *
- * Regardless of what happens to a backing {@code Activity} or @{code Service}, this lifecycle - * will only report itself as {@link Lifecycle.State#DESTROYED} when the associated {@link FlutterEngine} - * itself is destroyed. This is because a {@link Lifecycle} is not allowed to emit any events after - * going to the {@link Lifecycle.State#DESTROYED} state. Thus, this lifecycle cannot emit such an - * event until its associated {@link FlutterEngine} is destroyed. This then begs the question, what - * happens when the backing {@code Activity} or {@code Service} is destroyed? This lifecycle will - * report the process up to the {@link Lifecycle.Event#ON_STOP} event, but will ignore the - * {@link Lifecycle.Event#ON_DESTROY} event. At that point, this lifecycle will be back in its - * default {@link Lifecycle.State#CREATED} state until some other backing {@link Lifecycle} is - * registered. - */ -final class FlutterEngineAndroidLifecycle extends LifecycleRegistry { - private static final String TAG = "FlutterEngineAndroidLifecycle"; - - @Nullable - private Lifecycle backingLifecycle; - private boolean isDestroyed = false; - - @NonNull - private final LifecycleObserver forwardingObserver = new DefaultLifecycleObserver() { - @Override - public void onCreate(@NonNull LifecycleOwner owner) { - // No-op. The FlutterEngine's Lifecycle is always at least Created - // until it is Destroyed, so we ignore onCreate() events from - // backing Lifecycles. - } - - @Override - public void onStart(@NonNull LifecycleOwner owner) { - handleLifecycleEvent(Event.ON_START); - } - - @Override - public void onResume(@NonNull LifecycleOwner owner) { - handleLifecycleEvent(Event.ON_RESUME); - } - - @Override - public void onPause(@NonNull LifecycleOwner owner) { - handleLifecycleEvent(Event.ON_PAUSE); - } - - @Override - public void onStop(@NonNull LifecycleOwner owner) { - handleLifecycleEvent(Event.ON_STOP); - } - - @Override - public void onDestroy(@NonNull LifecycleOwner owner) { - // No-op. We don't allow FlutterEngine's Lifecycle to report destruction - // until the FlutterEngine itself is destroyed. This is because a Lifecycle - // is contractually obligated to send no more event once it gets to the - // Destroyed state, which would prevent FlutterEngine from switching to - // the next Lifecycle that is attached. - } - }; - - FlutterEngineAndroidLifecycle(@NonNull LifecycleOwner provider) { - super(provider); - } - - public void setBackingLifecycle(@Nullable Lifecycle lifecycle) { - ensureNotDestroyed(); - - // We no longer want to propagate events from the old Lifecycle. Deregister our forwarding observer. - if (backingLifecycle != null) { - backingLifecycle.removeObserver(forwardingObserver); - } - - // Manually move us to the Stopped state before we switch out the underlying Lifecycle. - handleLifecycleEvent(Event.ON_STOP); - - // Switch out the underlying lifecycle. - backingLifecycle = lifecycle; - - if (backingLifecycle != null) { - // Add our forwardingObserver to the new backing Lifecycle so that this PluginRegistry is - // controlled by that backing lifecycle. Adding our forwarding observer will automatically - // result in invocations of the necessary Lifecycle events to bring us up to speed with the - // new backingLifecycle, e.g., onStart(), onResume(). - lifecycle.addObserver(forwardingObserver); - } - } - - @Override - public void handleLifecycleEvent(@NonNull Event event) { - ensureNotDestroyed(); - super.handleLifecycleEvent(event); - } - - public void destroy() { - ensureNotDestroyed(); - setBackingLifecycle(null); - markState(State.DESTROYED); - isDestroyed = true; - } - - private void ensureNotDestroyed() { - if (isDestroyed) { - throw new IllegalStateException("Tried to invoke a method on a destroyed FlutterEngineAndroidLifecycle."); - } - } -} diff --git a/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEnginePluginRegistry.java b/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEnginePluginRegistry.java index efa756acc31..eb77bf41776 100644 --- a/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEnginePluginRegistry.java +++ b/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEnginePluginRegistry.java @@ -53,8 +53,6 @@ class FlutterEnginePluginRegistry implements PluginRegistry, private final FlutterEngine flutterEngine; @NonNull private final FlutterPlugin.FlutterPluginBinding pluginBinding; - @NonNull - private final FlutterEngineAndroidLifecycle flutterEngineAndroidLifecycle; // ActivityAware @NonNull @@ -91,18 +89,15 @@ class FlutterEnginePluginRegistry implements PluginRegistry, FlutterEnginePluginRegistry( @NonNull Context appContext, - @NonNull FlutterEngine flutterEngine, - @NonNull FlutterEngineAndroidLifecycle lifecycle + @NonNull FlutterEngine flutterEngine ) { this.flutterEngine = flutterEngine; - flutterEngineAndroidLifecycle = lifecycle; pluginBinding = new FlutterPlugin.FlutterPluginBinding( appContext, flutterEngine, flutterEngine.getDartExecutor(), flutterEngine.getRenderer(), - flutterEngine.getPlatformViewsController().getRegistry(), - lifecycle + flutterEngine.getPlatformViewsController().getRegistry() ); } @@ -113,11 +108,6 @@ class FlutterEnginePluginRegistry implements PluginRegistry, // plugins have an opportunity to clean up references as a result of component detachment. detachFromAndroidComponent(); - // Push FlutterEngine's Lifecycle to the DESTROYED state. This must happen before removing all - // plugins so that the plugins have an opportunity to clean up references as a result of moving - // to the DESTROYED state. - flutterEngineAndroidLifecycle.destroy(); - // Remove all registered plugins. removeAll(); } @@ -296,7 +286,6 @@ class FlutterEnginePluginRegistry implements PluginRegistry, this.activity = activity; this.activityPluginBinding = new FlutterEngineActivityPluginBinding(activity, lifecycle); - this.flutterEngineAndroidLifecycle.setBackingLifecycle(lifecycle); // Activate the PlatformViewsController. This must happen before any plugins attempt // to use it, otherwise an error stack trace will appear that says there is no @@ -331,7 +320,6 @@ class FlutterEnginePluginRegistry implements PluginRegistry, // Deactivate PlatformViewsController. flutterEngine.getPlatformViewsController().detach(); - flutterEngineAndroidLifecycle.setBackingLifecycle(null); activity = null; activityPluginBinding = null; } else { @@ -350,7 +338,6 @@ class FlutterEnginePluginRegistry implements PluginRegistry, // Deactivate PlatformViewsController. flutterEngine.getPlatformViewsController().detach(); - flutterEngineAndroidLifecycle.setBackingLifecycle(null); activity = null; activityPluginBinding = null; } else { @@ -434,7 +421,6 @@ class FlutterEnginePluginRegistry implements PluginRegistry, this.service = service; this.servicePluginBinding = new FlutterEngineServicePluginBinding(service, lifecycle); - flutterEngineAndroidLifecycle.setBackingLifecycle(lifecycle); // Notify all ServiceAware plugins that they are now attached to a new Service. for (ServiceAware serviceAware : serviceAwarePlugins.values()) { @@ -451,7 +437,6 @@ class FlutterEnginePluginRegistry implements PluginRegistry, serviceAware.onDetachedFromService(); } - flutterEngineAndroidLifecycle.setBackingLifecycle(null); service = null; servicePluginBinding = null; } else { diff --git a/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/plugins/FlutterPlugin.java b/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/plugins/FlutterPlugin.java index eaefdea8844..a32daa06856 100644 --- a/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/plugins/FlutterPlugin.java +++ b/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/plugins/FlutterPlugin.java @@ -5,7 +5,6 @@ package io.flutter.embedding.engine.plugins; import android.arch.lifecycle.Lifecycle; -import android.arch.lifecycle.LifecycleOwner; import android.content.Context; import android.support.annotation.NonNull; @@ -86,28 +85,25 @@ public interface FlutterPlugin { * {@link ActivityAware} and/or {@link ServiceAware} interfaces, where a {@link Lifecycle} * reference can be obtained. */ - class FlutterPluginBinding implements LifecycleOwner { + class FlutterPluginBinding { private final Context applicationContext; private final FlutterEngine flutterEngine; private final BinaryMessenger binaryMessenger; private final TextureRegistry textureRegistry; private final PlatformViewRegistry platformViewRegistry; - private final Lifecycle lifecycle; public FlutterPluginBinding( @NonNull Context applicationContext, @NonNull FlutterEngine flutterEngine, @NonNull BinaryMessenger binaryMessenger, @NonNull TextureRegistry textureRegistry, - @NonNull PlatformViewRegistry platformViewRegistry, - @NonNull Lifecycle lifecycle + @NonNull PlatformViewRegistry platformViewRegistry ) { this.applicationContext = applicationContext; this.flutterEngine = flutterEngine; this.binaryMessenger = binaryMessenger; this.textureRegistry = textureRegistry; this.platformViewRegistry = platformViewRegistry; - this.lifecycle = lifecycle; } @NonNull @@ -140,16 +136,5 @@ public interface FlutterPlugin { public PlatformViewRegistry getPlatformViewRegistry() { return platformViewRegistry; } - - /** - * @deprecated - * Use ActivityPluginBinding Lifecycle or ServicePluginBinding Lifecycle instead. - */ - @Deprecated - @Override - @NonNull - public Lifecycle getLifecycle() { - return lifecycle; - } } } diff --git a/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/plugins/activity/ActivityAware.java b/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/plugins/activity/ActivityAware.java index 332a275c03c..da542ba802d 100644 --- a/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/plugins/activity/ActivityAware.java +++ b/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/plugins/activity/ActivityAware.java @@ -47,6 +47,10 @@ public interface ActivityAware { * new {@link Activity} has been created with the new configuration options. That method provides * a new {@link ActivityPluginBinding}, which references the newly created and associated * {@link Activity}. + *
+ * Any {@code Lifecycle} listeners that were registered in + * {@link #onAttachedToActivity(ActivityPluginBinding)} should be deregistered here to avoid a + * possible memory leak and other side effects. */ void onDetachedFromActivityForConfigChanges(); @@ -76,6 +80,11 @@ public interface ActivityAware { * By the end of this method, the {@link Activity} that was made available in * {@link #onAttachedToActivity(ActivityPluginBinding)} is no longer valid. Any references to the * associated {@link Activity} or {@link ActivityPluginBinding} should be cleared. + *
+ * Any {@code Lifecycle} listeners that were registered in + * {@link #onAttachedToActivity(ActivityPluginBinding)} or + * {@link #onReattachedToActivityForConfigChanges(ActivityPluginBinding)} should be deregistered + * here to avoid a possible memory leak and other side effects. */ void onDetachedFromActivity(); } diff --git a/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/plugins/service/ServiceAware.java b/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/plugins/service/ServiceAware.java index be89a747c53..6445d148bf2 100644 --- a/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/plugins/service/ServiceAware.java +++ b/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/plugins/service/ServiceAware.java @@ -19,6 +19,10 @@ public interface ServiceAware { /** * Callback triggered when a {@code ServiceAware} {@link FlutterPlugin} is detached from a * {@link Service}. + *
+ * Any {@code Lifecycle} listeners that were registered in + * {@link #onAttachedToService(ServicePluginBinding)} should be deregistered here to avoid a + * possible memory leak and other side effects. */ void onDetachedFromService();