1 // Copyright 2013 The Flutter Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package io.flutter.embedding.engine; 6 7 import android.arch.lifecycle.DefaultLifecycleObserver; 8 import android.arch.lifecycle.Lifecycle; 9 import android.arch.lifecycle.LifecycleObserver; 10 import android.arch.lifecycle.LifecycleOwner; 11 import android.arch.lifecycle.LifecycleRegistry; 12 import android.support.annotation.NonNull; 13 import android.support.annotation.Nullable; 14 15 /** 16 * Android {@link Lifecycle} that is owned by a {@link FlutterEngine}. 17 * <p> 18 * {@code FlutterEngineAndroidLifecycle} exists so that {@code FlutterPlugin}s can monitor Android 19 * lifecycle events. When the associated {@link FlutterEngine} is running in an {@code Activity}, 20 * that {@code Activity}'s {@link Lifecycle} can be set as the {@code backingLifecycle} of this 21 * class, allowing all Flutter plugins to receive the {@code Activity}'s lifecycle events. Likewise, 22 * when the associated {@link FlutterEngine} is running in a {@code Service}, that {@code Service}'s 23 * {@link Lifecycle} can be set as the {@code backingLifecycle}. 24 * <p> 25 * Sometimes a {@link FlutterEngine} exists in a non-lifecycle location, e.g., an {@code Application}, 26 * {@code ContentProvider}, or {@code BroadcastReceiver}. In these cases, this lifecycle reports 27 * itself in the {@link Lifecycle.State#CREATED} state. 28 * <p> 29 * Regardless of what happens to a backing {@code Activity} or @{code Service}, this lifecycle 30 * will only report itself as {@link Lifecycle.State#DESTROYED} when the associated {@link FlutterEngine} 31 * itself is destroyed. This is because a {@link Lifecycle} is not allowed to emit any events after 32 * going to the {@link Lifecycle.State#DESTROYED} state. Thus, this lifecycle cannot emit such an 33 * event until its associated {@link FlutterEngine} is destroyed. This then begs the question, what 34 * happens when the backing {@code Activity} or {@code Service} is destroyed? This lifecycle will 35 * report the process up to the {@link Lifecycle.Event#ON_STOP} event, but will ignore the 36 * {@link Lifecycle.Event#ON_DESTROY} event. At that point, this lifecycle will be back in its 37 * default {@link Lifecycle.State#CREATED} state until some other backing {@link Lifecycle} is 38 * registered. 39 */ 40 final class FlutterEngineAndroidLifecycle extends LifecycleRegistry { 41 private static final String TAG = "FlutterEngineAndroidLifecycle"; 42 43 @Nullable 44 private Lifecycle backingLifecycle; 45 private boolean isDestroyed = false; 46 47 @NonNull 48 private final LifecycleObserver forwardingObserver = new DefaultLifecycleObserver() { 49 @Override 50 public void onCreate(@NonNull LifecycleOwner owner) { 51 // No-op. The FlutterEngine's Lifecycle is always at least Created 52 // until it is Destroyed, so we ignore onCreate() events from 53 // backing Lifecycles. 54 } 55 56 @Override 57 public void onStart(@NonNull LifecycleOwner owner) { 58 handleLifecycleEvent(Event.ON_START); 59 } 60 61 @Override 62 public void onResume(@NonNull LifecycleOwner owner) { 63 handleLifecycleEvent(Event.ON_RESUME); 64 } 65 66 @Override 67 public void onPause(@NonNull LifecycleOwner owner) { 68 handleLifecycleEvent(Event.ON_PAUSE); 69 } 70 71 @Override 72 public void onStop(@NonNull LifecycleOwner owner) { 73 handleLifecycleEvent(Event.ON_STOP); 74 } 75 76 @Override 77 public void onDestroy(@NonNull LifecycleOwner owner) { 78 // No-op. We don't allow FlutterEngine's Lifecycle to report destruction 79 // until the FlutterEngine itself is destroyed. This is because a Lifecycle 80 // is contractually obligated to send no more event once it gets to the 81 // Destroyed state, which would prevent FlutterEngine from switching to 82 // the next Lifecycle that is attached. 83 } 84 }; 85 FlutterEngineAndroidLifecycle(@onNull LifecycleOwner provider)86 FlutterEngineAndroidLifecycle(@NonNull LifecycleOwner provider) { 87 super(provider); 88 } 89 setBackingLifecycle(@ullable Lifecycle lifecycle)90 public void setBackingLifecycle(@Nullable Lifecycle lifecycle) { 91 ensureNotDestroyed(); 92 93 // We no longer want to propagate events from the old Lifecycle. Deregister our forwarding observer. 94 if (backingLifecycle != null) { 95 backingLifecycle.removeObserver(forwardingObserver); 96 } 97 98 // Manually move us to the Stopped state before we switch out the underlying Lifecycle. 99 handleLifecycleEvent(Event.ON_STOP); 100 101 // Switch out the underlying lifecycle. 102 backingLifecycle = lifecycle; 103 104 if (backingLifecycle != null) { 105 // Add our forwardingObserver to the new backing Lifecycle so that this PluginRegistry is 106 // controlled by that backing lifecycle. Adding our forwarding observer will automatically 107 // result in invocations of the necessary Lifecycle events to bring us up to speed with the 108 // new backingLifecycle, e.g., onStart(), onResume(). 109 lifecycle.addObserver(forwardingObserver); 110 } 111 } 112 113 @Override handleLifecycleEvent(@onNull Event event)114 public void handleLifecycleEvent(@NonNull Event event) { 115 ensureNotDestroyed(); 116 super.handleLifecycleEvent(event); 117 } 118 destroy()119 public void destroy() { 120 ensureNotDestroyed(); 121 setBackingLifecycle(null); 122 markState(State.DESTROYED); 123 isDestroyed = true; 124 } 125 ensureNotDestroyed()126 private void ensureNotDestroyed() { 127 if (isDestroyed) { 128 throw new IllegalStateException("Tried to invoke a method on a destroyed FlutterEngineAndroidLifecycle."); 129 } 130 } 131 } 132