[google_maps_flutter] Overhaul lifecycle management in GoogleMapsPlugin (#3213)

GoogleMapController is now uniformly driven by implementing DefaultLifecycleObserver. That observer is registered to a lifecycle passed via the new LifecycleProvider interface, which has 3 implementations:
1. For v2 plugin registration, GoogleMapsPlugin implements the interface and holds the lifecycle in a field, which is itself controlled by ActivityAware methods.
2. For v1 plugin registration, if the activity implements LifecycleOwner, it's lifecycle is used directly.
3. For v1 plugin registration, if the activity does not implement LifecycleOwner, a proxy lifecycle is created via ActivityLifecycleCallbacks.

diff --git a/packages/google_maps_flutter/google_maps_flutter/CHANGELOG.md b/packages/google_maps_flutter/google_maps_flutter/CHANGELOG.md
index afe8638..a2e0c1b 100644
--- a/packages/google_maps_flutter/google_maps_flutter/CHANGELOG.md
+++ b/packages/google_maps_flutter/google_maps_flutter/CHANGELOG.md
@@ -1,3 +1,13 @@
+## 1.0.5
+
+Overhaul lifecycle management in GoogleMapsPlugin.
+
+GoogleMapController is now uniformly driven by implementing `DefaultLifecycleObserver`. That observer is registered to a lifecycle from one of three sources:
+
+1. For v2 plugin registration, `GoogleMapsPlugin` obtains the lifecycle via `ActivityAware` methods.
+2. For v1 plugin registration, if the activity implements `LifecycleOwner`, it's lifecycle is used directly.
+3. For v1 plugin registration, if the activity does not implement `LifecycleOwner`, a proxy lifecycle is created and driven via `ActivityLifecycleCallbacks`.
+
 ## 1.0.4
 
 * Cleanup of Android code:
diff --git a/packages/google_maps_flutter/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapBuilder.java b/packages/google_maps_flutter/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapBuilder.java
index ca47be8..93a3c3e 100644
--- a/packages/google_maps_flutter/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapBuilder.java
+++ b/packages/google_maps_flutter/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapBuilder.java
@@ -4,17 +4,12 @@
 
 package io.flutter.plugins.googlemaps;
 
-import android.app.Application;
 import android.content.Context;
 import android.graphics.Rect;
-import androidx.annotation.Nullable;
-import androidx.lifecycle.Lifecycle;
-import androidx.lifecycle.Lifecycle.State;
 import com.google.android.gms.maps.GoogleMapOptions;
 import com.google.android.gms.maps.model.CameraPosition;
 import com.google.android.gms.maps.model.LatLngBounds;
 import io.flutter.plugin.common.BinaryMessenger;
-import io.flutter.plugin.common.PluginRegistry;
 
 class GoogleMapBuilder implements GoogleMapOptionsSink {
   private final GoogleMapOptions options = new GoogleMapOptions();
@@ -33,15 +28,11 @@
   GoogleMapController build(
       int id,
       Context context,
-      State lifecycleState,
       BinaryMessenger binaryMessenger,
-      @Nullable Application application,
-      @Nullable Lifecycle lifecycle,
-      @Nullable PluginRegistry.Registrar registrar) {
+      LifecycleProvider lifecycleProvider) {
     final GoogleMapController controller =
-        new GoogleMapController(
-            id, context, binaryMessenger, application, lifecycle, registrar, options);
-    controller.init(lifecycleState);
+        new GoogleMapController(id, context, binaryMessenger, lifecycleProvider, options);
+    controller.init();
     controller.setMyLocationEnabled(myLocationEnabled);
     controller.setMyLocationButtonEnabled(myLocationButtonEnabled);
     controller.setIndoorEnabled(indoorEnabled);
diff --git a/packages/google_maps_flutter/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapController.java b/packages/google_maps_flutter/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapController.java
index ea3322d..33cacff 100644
--- a/packages/google_maps_flutter/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapController.java
+++ b/packages/google_maps_flutter/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapController.java
@@ -6,8 +6,6 @@
 
 import android.Manifest;
 import android.annotation.SuppressLint;
-import android.app.Activity;
-import android.app.Application;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.graphics.Bitmap;
@@ -19,7 +17,6 @@
 import androidx.annotation.Nullable;
 import androidx.lifecycle.DefaultLifecycleObserver;
 import androidx.lifecycle.Lifecycle;
-import androidx.lifecycle.Lifecycle.State;
 import androidx.lifecycle.LifecycleOwner;
 import com.google.android.gms.maps.CameraUpdate;
 import com.google.android.gms.maps.GoogleMap;
@@ -39,7 +36,6 @@
 import io.flutter.plugin.common.BinaryMessenger;
 import io.flutter.plugin.common.MethodCall;
 import io.flutter.plugin.common.MethodChannel;
-import io.flutter.plugin.common.PluginRegistry;
 import io.flutter.plugin.platform.PlatformView;
 import java.io.ByteArrayOutputStream;
 import java.util.ArrayList;
@@ -50,8 +46,7 @@
 
 /** Controller of a single GoogleMaps MapView instance. */
 final class GoogleMapController
-    implements Application.ActivityLifecycleCallbacks,
-        DefaultLifecycleObserver,
+    implements DefaultLifecycleObserver,
         ActivityPluginBinding.OnSaveInstanceStateListener,
         GoogleMapOptionsSink,
         MethodChannel.MethodCallHandler,
@@ -75,12 +70,8 @@
   private boolean disposed = false;
   private final float density;
   private MethodChannel.Result mapReadyResult;
-  @Nullable private final Lifecycle lifecycle;
   private final Context context;
-  // Do not use directly, use getApplication() instead to get correct application object for both v1
-  // and v2 embedding.
-  @Nullable private final Application mApplication;
-  @Nullable private final PluginRegistry.Registrar registrar; // For v1 embedding only.
+  private final LifecycleProvider lifecycleProvider;
   private final MarkersController markersController;
   private final PolygonsController polygonsController;
   private final PolylinesController polylinesController;
@@ -94,9 +85,7 @@
       int id,
       Context context,
       BinaryMessenger binaryMessenger,
-      @Nullable Application application,
-      @Nullable Lifecycle lifecycle,
-      @Nullable PluginRegistry.Registrar registrar,
+      LifecycleProvider lifecycleProvider,
       GoogleMapOptions options) {
     this.id = id;
     this.context = context;
@@ -105,9 +94,7 @@
     this.density = context.getResources().getDisplayMetrics().density;
     methodChannel = new MethodChannel(binaryMessenger, "plugins.flutter.io/google_maps_" + id);
     methodChannel.setMethodCallHandler(this);
-    mApplication = application;
-    this.lifecycle = lifecycle;
-    this.registrar = registrar;
+    this.lifecycleProvider = lifecycleProvider;
     this.markersController = new MarkersController(methodChannel);
     this.polygonsController = new PolygonsController(methodChannel, density);
     this.polylinesController = new PolylinesController(methodChannel, density);
@@ -119,30 +106,8 @@
     return mapView;
   }
 
-  void init(State lifecycleState) {
-    switch (lifecycleState) {
-      case RESUMED:
-        mapView.onCreate(null);
-        mapView.onStart();
-        mapView.onResume();
-        break;
-      case STARTED:
-        mapView.onCreate(null);
-        mapView.onStart();
-        break;
-      case CREATED:
-        mapView.onCreate(null);
-        break;
-      case DESTROYED:
-      case INITIALIZED:
-        // Nothing to do, the activity has been completely destroyed or not yet created.
-        break;
-    }
-    if (lifecycle != null) {
-      lifecycle.addObserver(this);
-    } else {
-      getApplication().registerActivityLifecycleCallbacks(this);
-    }
+  void init() {
+    lifecycleProvider.getLifecycle().addObserver(this);
     mapView.getMapAsync(this);
   }
 
@@ -507,7 +472,10 @@
     methodChannel.setMethodCallHandler(null);
     setGoogleMapListener(null);
     destroyMapViewIfNecessary();
-    getApplication().unregisterActivityLifecycleCallbacks(this);
+    Lifecycle lifecycle = lifecycleProvider.getLifecycle();
+    if (lifecycle != null) {
+      lifecycle.removeObserver(this);
+    }
   }
 
   private void setGoogleMapListener(@Nullable GoogleMapListener listener) {
@@ -537,64 +505,7 @@
     // TODO(mklim): Remove this empty override once https://github.com/flutter/flutter/issues/40126 is fixed in stable.
   }
 
-  // Application.ActivityLifecycleCallbacks methods
-  @Override
-  public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
-    if (disposed || activity.hashCode() != getActivityHashCode()) {
-      return;
-    }
-    mapView.onCreate(savedInstanceState);
-  }
-
-  @Override
-  public void onActivityStarted(Activity activity) {
-    if (disposed || activity.hashCode() != getActivityHashCode()) {
-      return;
-    }
-    mapView.onStart();
-  }
-
-  @Override
-  public void onActivityResumed(Activity activity) {
-    if (disposed || activity.hashCode() != getActivityHashCode()) {
-      return;
-    }
-    mapView.onResume();
-  }
-
-  @Override
-  public void onActivityPaused(Activity activity) {
-    if (disposed || activity.hashCode() != getActivityHashCode()) {
-      return;
-    }
-    mapView.onPause();
-  }
-
-  @Override
-  public void onActivityStopped(Activity activity) {
-    if (disposed || activity.hashCode() != getActivityHashCode()) {
-      return;
-    }
-    mapView.onStop();
-  }
-
-  @Override
-  public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
-    if (disposed || activity.hashCode() != getActivityHashCode()) {
-      return;
-    }
-    mapView.onSaveInstanceState(outState);
-  }
-
-  @Override
-  public void onActivityDestroyed(Activity activity) {
-    if (disposed || activity.hashCode() != getActivityHashCode()) {
-      return;
-    }
-    destroyMapViewIfNecessary();
-  }
-
-  // DefaultLifecycleObserver and OnSaveInstanceStateListener
+  // DefaultLifecycleObserver
 
   @Override
   public void onCreate(@NonNull LifecycleOwner owner) {
@@ -638,6 +549,7 @@
 
   @Override
   public void onDestroy(@NonNull LifecycleOwner owner) {
+    owner.getLifecycle().removeObserver(this);
     if (disposed) {
       return;
     }
@@ -848,24 +760,6 @@
         permission, android.os.Process.myPid(), android.os.Process.myUid());
   }
 
-  private int getActivityHashCode() {
-    if (registrar != null && registrar.activity() != null) {
-      return registrar.activity().hashCode();
-    } else {
-      // TODO(cyanglaz): Remove `getActivityHashCode()` and use a cached hashCode when creating the view for V1 embedding.
-      // https://github.com/flutter/flutter/issues/69128
-      return -1;
-    }
-  }
-
-  private Application getApplication() {
-    if (registrar != null && registrar.activity() != null) {
-      return registrar.activity().getApplication();
-    } else {
-      return mApplication;
-    }
-  }
-
   private void destroyMapViewIfNecessary() {
     if (mapView == null) {
       return;
diff --git a/packages/google_maps_flutter/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapFactory.java b/packages/google_maps_flutter/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapFactory.java
index 7d665d4..e56adbb 100644
--- a/packages/google_maps_flutter/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapFactory.java
+++ b/packages/google_maps_flutter/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapFactory.java
@@ -4,40 +4,23 @@
 
 package io.flutter.plugins.googlemaps;
 
-import android.app.Application;
 import android.content.Context;
-import androidx.annotation.Nullable;
-import androidx.lifecycle.Lifecycle;
-import androidx.lifecycle.Lifecycle.State;
 import com.google.android.gms.maps.model.CameraPosition;
 import io.flutter.plugin.common.BinaryMessenger;
-import io.flutter.plugin.common.PluginRegistry;
 import io.flutter.plugin.common.StandardMessageCodec;
 import io.flutter.plugin.platform.PlatformView;
 import io.flutter.plugin.platform.PlatformViewFactory;
 import java.util.Map;
-import java.util.concurrent.atomic.AtomicReference;
 
 public class GoogleMapFactory extends PlatformViewFactory {
 
-  private final AtomicReference<State> lifecycleState;
   private final BinaryMessenger binaryMessenger;
-  @Nullable private final Application application;
-  @Nullable private final Lifecycle lifecycle;
-  @Nullable private final PluginRegistry.Registrar registrar; // V1 embedding only.
+  private final LifecycleProvider lifecycleProvider;
 
-  GoogleMapFactory(
-      AtomicReference<State> lifecycleState,
-      BinaryMessenger binaryMessenger,
-      @Nullable Application application,
-      @Nullable Lifecycle lifecycle,
-      @Nullable PluginRegistry.Registrar registrar) {
+  GoogleMapFactory(BinaryMessenger binaryMessenger, LifecycleProvider lifecycleProvider) {
     super(StandardMessageCodec.INSTANCE);
-    this.lifecycleState = lifecycleState;
     this.binaryMessenger = binaryMessenger;
-    this.application = application;
-    this.lifecycle = lifecycle;
-    this.registrar = registrar;
+    this.lifecycleProvider = lifecycleProvider;
   }
 
   @SuppressWarnings("unchecked")
@@ -63,7 +46,6 @@
     if (params.containsKey("circlesToAdd")) {
       builder.setInitialCircles(params.get("circlesToAdd"));
     }
-    return builder.build(
-        id, context, lifecycleState.get(), binaryMessenger, application, lifecycle, registrar);
+    return builder.build(id, context, binaryMessenger, lifecycleProvider);
   }
 }
diff --git a/packages/google_maps_flutter/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapsPlugin.java b/packages/google_maps_flutter/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapsPlugin.java
index 811ea97..69ba8cb 100644
--- a/packages/google_maps_flutter/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapsPlugin.java
+++ b/packages/google_maps_flutter/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapsPlugin.java
@@ -4,25 +4,19 @@
 
 package io.flutter.plugins.googlemaps;
 
-import static androidx.lifecycle.Lifecycle.State.CREATED;
-import static androidx.lifecycle.Lifecycle.State.DESTROYED;
-import static androidx.lifecycle.Lifecycle.State.INITIALIZED;
-import static androidx.lifecycle.Lifecycle.State.RESUMED;
-import static androidx.lifecycle.Lifecycle.State.STARTED;
-
 import android.app.Activity;
-import android.app.Application;
+import android.app.Application.ActivityLifecycleCallbacks;
 import android.os.Bundle;
 import androidx.annotation.NonNull;
-import androidx.lifecycle.DefaultLifecycleObserver;
+import androidx.annotation.Nullable;
 import androidx.lifecycle.Lifecycle;
-import androidx.lifecycle.Lifecycle.State;
+import androidx.lifecycle.Lifecycle.Event;
 import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.LifecycleRegistry;
 import io.flutter.embedding.engine.plugins.FlutterPlugin;
 import io.flutter.embedding.engine.plugins.activity.ActivityAware;
 import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
 import io.flutter.embedding.engine.plugins.lifecycle.FlutterLifecycleAdapter;
-import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * Plugin for controlling a set of GoogleMap views to be shown as overlays on top of the Flutter
@@ -30,170 +24,162 @@
  * the map. A Texture drawn using GoogleMap bitmap snapshots can then be shown instead of the
  * overlay.
  */
-public class GoogleMapsPlugin
-    implements Application.ActivityLifecycleCallbacks,
-        FlutterPlugin,
-        ActivityAware,
-        DefaultLifecycleObserver {
-  private final AtomicReference<State> state = new AtomicReference<>(INITIALIZED);
-  private int registrarActivityHashCode;
-  private FlutterPluginBinding pluginBinding;
-  private Lifecycle lifecycle;
+public class GoogleMapsPlugin implements FlutterPlugin, ActivityAware {
+
+  @Nullable private Lifecycle lifecycle;
 
   private static final String VIEW_TYPE = "plugins.flutter.io/google_maps";
 
   @SuppressWarnings("deprecation")
-  public static void registerWith(io.flutter.plugin.common.PluginRegistry.Registrar registrar) {
-    if (registrar.activity() == null) {
+  public static void registerWith(
+      final io.flutter.plugin.common.PluginRegistry.Registrar registrar) {
+    final Activity activity = registrar.activity();
+    if (activity == null) {
       // When a background flutter view tries to register the plugin, the registrar has no activity.
       // We stop the registration process as this plugin is foreground only.
       return;
     }
-    final GoogleMapsPlugin plugin = new GoogleMapsPlugin(registrar.activity());
-    registrar.activity().getApplication().registerActivityLifecycleCallbacks(plugin);
-    registrar
-        .platformViewRegistry()
-        .registerViewFactory(
-            VIEW_TYPE,
-            new GoogleMapFactory(plugin.state, registrar.messenger(), null, null, registrar));
+    if (activity instanceof LifecycleOwner) {
+      registrar
+          .platformViewRegistry()
+          .registerViewFactory(
+              VIEW_TYPE,
+              new GoogleMapFactory(
+                  registrar.messenger(),
+                  new LifecycleProvider() {
+                    @Override
+                    public Lifecycle getLifecycle() {
+                      return ((LifecycleOwner) activity).getLifecycle();
+                    }
+                  }));
+    } else {
+      registrar
+          .platformViewRegistry()
+          .registerViewFactory(
+              VIEW_TYPE,
+              new GoogleMapFactory(registrar.messenger(), new ProxyLifecycleProvider(activity)));
+    }
   }
 
   public GoogleMapsPlugin() {}
 
-  private GoogleMapsPlugin(Activity activity) {
-    this.registrarActivityHashCode = activity.hashCode();
-  }
-
   // FlutterPlugin
 
   @Override
   public void onAttachedToEngine(FlutterPluginBinding binding) {
-    pluginBinding = binding;
+    binding
+        .getPlatformViewRegistry()
+        .registerViewFactory(
+            VIEW_TYPE,
+            new GoogleMapFactory(
+                binding.getBinaryMessenger(),
+                new LifecycleProvider() {
+                  @Nullable
+                  @Override
+                  public Lifecycle getLifecycle() {
+                    return lifecycle;
+                  }
+                }));
   }
 
   @Override
-  public void onDetachedFromEngine(FlutterPluginBinding binding) {
-    pluginBinding = null;
-  }
+  public void onDetachedFromEngine(FlutterPluginBinding binding) {}
 
   // ActivityAware
 
   @Override
   public void onAttachedToActivity(ActivityPluginBinding binding) {
     lifecycle = FlutterLifecycleAdapter.getActivityLifecycle(binding);
-    lifecycle.addObserver(this);
-    pluginBinding
-        .getPlatformViewRegistry()
-        .registerViewFactory(
-            VIEW_TYPE,
-            new GoogleMapFactory(
-                state,
-                pluginBinding.getBinaryMessenger(),
-                binding.getActivity().getApplication(),
-                lifecycle,
-                null));
   }
 
   @Override
   public void onDetachedFromActivity() {
-    lifecycle.removeObserver(this);
     lifecycle = null;
   }
 
   @Override
-  public void onDetachedFromActivityForConfigChanges() {
-    this.onDetachedFromActivity();
-  }
-
-  @Override
   public void onReattachedToActivityForConfigChanges(ActivityPluginBinding binding) {
-    lifecycle = FlutterLifecycleAdapter.getActivityLifecycle(binding);
-    lifecycle.addObserver(this);
-  }
-
-  // DefaultLifecycleObserver methods
-
-  @Override
-  public void onCreate(@NonNull LifecycleOwner owner) {
-    state.set(CREATED);
+    onAttachedToActivity(binding);
   }
 
   @Override
-  public void onStart(@NonNull LifecycleOwner owner) {
-    state.set(STARTED);
+  public void onDetachedFromActivityForConfigChanges() {
+    onDetachedFromActivity();
   }
 
-  @Override
-  public void onResume(@NonNull LifecycleOwner owner) {
-    state.set(RESUMED);
-  }
+  /**
+   * This class provides a {@link LifecycleOwner} for the activity driven by {@link
+   * ActivityLifecycleCallbacks}.
+   *
+   * <p>This is used in the case where a direct Lifecycle/Owner is not available.
+   */
+  private static final class ProxyLifecycleProvider
+      implements ActivityLifecycleCallbacks, LifecycleOwner, LifecycleProvider {
 
-  @Override
-  public void onPause(@NonNull LifecycleOwner owner) {
-    state.set(STARTED);
-  }
+    private final LifecycleRegistry lifecycle = new LifecycleRegistry(this);
+    private final int registrarActivityHashCode;
 
-  @Override
-  public void onStop(@NonNull LifecycleOwner owner) {
-    state.set(CREATED);
-  }
-
-  @Override
-  public void onDestroy(@NonNull LifecycleOwner owner) {
-    state.set(DESTROYED);
-  }
-
-  // Application.ActivityLifecycleCallbacks methods
-
-  @Override
-  public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
-    if (activity.hashCode() != registrarActivityHashCode) {
-      return;
+    private ProxyLifecycleProvider(Activity activity) {
+      this.registrarActivityHashCode = activity.hashCode();
+      activity.getApplication().registerActivityLifecycleCallbacks(this);
     }
-    state.set(CREATED);
-  }
 
-  @Override
-  public void onActivityStarted(Activity activity) {
-    if (activity.hashCode() != registrarActivityHashCode) {
-      return;
+    @Override
+    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
+      if (activity.hashCode() != registrarActivityHashCode) {
+        return;
+      }
+      lifecycle.handleLifecycleEvent(Event.ON_CREATE);
     }
-    state.set(STARTED);
-  }
 
-  @Override
-  public void onActivityResumed(Activity activity) {
-    if (activity.hashCode() != registrarActivityHashCode) {
-      return;
+    @Override
+    public void onActivityStarted(Activity activity) {
+      if (activity.hashCode() != registrarActivityHashCode) {
+        return;
+      }
+      lifecycle.handleLifecycleEvent(Event.ON_START);
     }
-    state.set(RESUMED);
-  }
 
-  @Override
-  public void onActivityPaused(Activity activity) {
-    if (activity.hashCode() != registrarActivityHashCode) {
-      return;
+    @Override
+    public void onActivityResumed(Activity activity) {
+      if (activity.hashCode() != registrarActivityHashCode) {
+        return;
+      }
+      lifecycle.handleLifecycleEvent(Event.ON_RESUME);
     }
-    state.set(STARTED);
-  }
 
-  @Override
-  public void onActivityStopped(Activity activity) {
-    if (activity.hashCode() != registrarActivityHashCode) {
-      return;
+    @Override
+    public void onActivityPaused(Activity activity) {
+      if (activity.hashCode() != registrarActivityHashCode) {
+        return;
+      }
+      lifecycle.handleLifecycleEvent(Event.ON_PAUSE);
     }
-    state.set(CREATED);
-  }
 
-  @Override
-  public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}
-
-  @Override
-  public void onActivityDestroyed(Activity activity) {
-    if (activity.hashCode() != registrarActivityHashCode) {
-      return;
+    @Override
+    public void onActivityStopped(Activity activity) {
+      if (activity.hashCode() != registrarActivityHashCode) {
+        return;
+      }
+      lifecycle.handleLifecycleEvent(Event.ON_STOP);
     }
-    activity.getApplication().unregisterActivityLifecycleCallbacks(this);
-    state.set(DESTROYED);
+
+    @Override
+    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}
+
+    @Override
+    public void onActivityDestroyed(Activity activity) {
+      if (activity.hashCode() != registrarActivityHashCode) {
+        return;
+      }
+      activity.getApplication().unregisterActivityLifecycleCallbacks(this);
+      lifecycle.handleLifecycleEvent(Event.ON_DESTROY);
+    }
+
+    @NonNull
+    @Override
+    public Lifecycle getLifecycle() {
+      return lifecycle;
+    }
   }
 }
diff --git a/packages/google_maps_flutter/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/LifecycleProvider.java b/packages/google_maps_flutter/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/LifecycleProvider.java
new file mode 100644
index 0000000..154de20
--- /dev/null
+++ b/packages/google_maps_flutter/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/LifecycleProvider.java
@@ -0,0 +1,14 @@
+// Copyright 2019 The Chromium 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.plugins.googlemaps;
+
+import androidx.annotation.Nullable;
+import androidx.lifecycle.Lifecycle;
+
+interface LifecycleProvider {
+
+  @Nullable
+  Lifecycle getLifecycle();
+}
diff --git a/packages/google_maps_flutter/google_maps_flutter/example/android/app/src/test/java/io/flutter/plugins/googlemaps/GoogleMapControllerTest.java b/packages/google_maps_flutter/google_maps_flutter/example/android/app/src/test/java/io/flutter/plugins/googlemaps/GoogleMapControllerTest.java
index 09f0c78..94b9347 100644
--- a/packages/google_maps_flutter/google_maps_flutter/example/android/app/src/test/java/io/flutter/plugins/googlemaps/GoogleMapControllerTest.java
+++ b/packages/google_maps_flutter/google_maps_flutter/example/android/app/src/test/java/io/flutter/plugins/googlemaps/GoogleMapControllerTest.java
@@ -3,10 +3,8 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
-import android.app.Application;
 import android.content.Context;
-import androidx.lifecycle.Lifecycle.State;
-import androidx.lifecycle.LifecycleOwner;
+import androidx.activity.ComponentActivity;
 import androidx.test.core.app.ApplicationProvider;
 import com.google.android.gms.maps.GoogleMap;
 import io.flutter.plugin.common.BinaryMessenger;
@@ -15,27 +13,27 @@
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
 import org.robolectric.RobolectricTestRunner;
 
 @RunWith(RobolectricTestRunner.class)
 public class GoogleMapControllerTest {
 
   private Context context;
-  private Application application;
+  private ComponentActivity activity;
   private GoogleMapController googleMapController;
 
   @Mock BinaryMessenger mockMessenger;
   @Mock GoogleMap mockGoogleMap;
-  @Mock LifecycleOwner lifecycleOwner;
 
   @Before
   public void before() {
     MockitoAnnotations.initMocks(this);
     context = ApplicationProvider.getApplicationContext();
-    application = ApplicationProvider.getApplicationContext();
+    activity = Robolectric.setupActivity(ComponentActivity.class);
     googleMapController =
-        new GoogleMapController(0, context, mockMessenger, application, null, null, null);
-    googleMapController.init(State.CREATED);
+        new GoogleMapController(0, context, mockMessenger, activity::getLifecycle, null);
+    googleMapController.init();
   }
 
   @Test
@@ -50,7 +48,7 @@
   public void OnDestroyReleaseTheMap() throws InterruptedException {
     googleMapController.onMapReady(mockGoogleMap);
     assertTrue(googleMapController != null);
-    googleMapController.onDestroy(lifecycleOwner);
+    googleMapController.onDestroy(activity);
     assertNull(googleMapController.getView());
   }
 }
diff --git a/packages/google_maps_flutter/google_maps_flutter/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter/pubspec.yaml
index 1c6ba4a..dadedb8 100644
--- a/packages/google_maps_flutter/google_maps_flutter/pubspec.yaml
+++ b/packages/google_maps_flutter/google_maps_flutter/pubspec.yaml
@@ -1,7 +1,7 @@
 name: google_maps_flutter
 description: A Flutter plugin for integrating Google Maps in iOS and Android applications.
 homepage: https://github.com/flutter/plugins/tree/master/packages/google_maps_flutter/google_maps_flutter
-version: 1.0.4
+version: 1.0.5
 
 dependencies:
   flutter: