Remove multiplexed Flutter Android Lifecycle. (#43663) (flutter/engine#13394)

This commit is contained in:
Matt Carroll 2019-10-28 16:22:11 -07:00 committed by GitHub
parent be943c8fc2
commit b2b2f011e7
8 changed files with 19 additions and 182 deletions

View File

@ -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

View File

@ -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",

View File

@ -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.
*/

View File

@ -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}.
* <p>
* {@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}.
* <p>
* 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.
* <p>
* 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.");
}
}
}

View File

@ -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 {

View File

@ -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;
}
}
}

View File

@ -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}.
* <p>
* 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.
* <p>
* 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();
}

View File

@ -19,6 +19,10 @@ public interface ServiceAware {
/**
* Callback triggered when a {@code ServiceAware} {@link FlutterPlugin} is detached from a
* {@link Service}.
* <p>
* 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();