• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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