旋转设备(纵向/横向)后如何在 MapFragment 上 preserve/rebind 事件监听器?

How to preserve/rebind event listeners on MapFragment after rotating the device (portrait / landscape)?

我正在使用 Xamarin(版本 7.1)开发 Android 应用程序。它显示为地图并绘制折线,在 OnCameraIdle().

中这样做

MapFragment 是在 OnCreate 中以编程方式生成的。我正在通过 GetMapAsyncOnResume 中获取 GoogleMap 并在 OnMapReady.
中绑定监听器 他们工作得很好,但只是在开始阶段。一旦设备旋转(纵向 -> 横向或反之),相机移动就不会再触发听众。
然而,地图有效 - 我(用户)仍然可以很好地移动相机。我(应用程序)无法再使用它了。

这是裸代码,只有地图创建和处理。其他所有内容(实际绘图)均已删除:

public class MapActivity : Activity, IOnMapReadyCallback, 
    GoogleMap.IOnCameraIdleListener, GoogleMap.IOnCameraMoveStartedListener
{
    private GoogleMap _map;
    private MapFragment _mapFragment;

    private void InitializeMap()
    {
        _mapFragment = MapFragment.NewInstance();
        var tx = FragmentManager.BeginTransaction();
        tx.Add(Resource.Id.map_placeholder, _mapFragment);
        tx.Commit();
    }

    private void SetMapListeners()
    {
        Log.Debug("MyApp/ Map", "SetMapListeners");
        _map.SetOnCameraIdleListener(this);
        _map.SetOnCameraMoveStartedListener(this);
    }

    /* Activity */

    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        Log.Debug("MyApp / Map", "OnCreate");
        SetContentView(Resource.Layout.Map);
        InitializeMap();
    }

    protected override void OnStart()
    {
        base.OnStart();
        Log.Debug("MyApp / Map", "OnStart");
    }

    protected override void OnResume()
    {
        base.OnResume();
        if (_map == null)
            _mapFragment.GetMapAsync(this);
        Log.Debug("MyApp / Map", "OnResume");
    }

    protected override void OnPause()
    {
        base.OnPause();
        Log.Debug("MyApp / Map", "OnPause");
    }

    protected override void OnStop()
    {
        base.OnStop();
        Log.Debug("MyApp / Map", "OnStop");
    }

    protected override void OnDestroy()
    {
        base.OnStop();
        Log.Debug("MyApp/ Map", "OnDestroy");
    }


    /* IOnMapReadyCallback */   

    public void OnMapReady(GoogleMap googleMap)
    {
        Log.Debug("MyApp / Map", "Map is ready!");
        _map = googleMap;       
        SetMapListeners();
    }


    /* IOnCameraIdleListener */

    public void OnCameraIdle()
    {
        Log.Debug("MyApp / Map", "Camera is idle.");
        // Drawing routine is called here
    }


    /* IOnCameraMoveStartedListener */

    public void OnCameraMoveStarted(int reason)
    {
        Log.Debug("MyApp / Map", "Camera move started.");
    }
}

正如您在以下日志摘录中看到的那样,侦听器在开始时确实起作用,但是一旦设备旋转(至少)一次,它们就消失了。
我还尝试在生命周期中只调用一次 SetMapListeners,第一次调用 OnMapReady,但这并没有改变任何东西。

04-03 20:29:06.486 D/MyApp / Map( 7446): OnCreate
04-03 20:29:06.688 I/Google Maps Android API( 7446): Google Play services client version: 10084000
04-03 20:29:06.695 I/Google Maps Android API( 7446): Google Play services package version: 10298438
04-03 20:29:07.394 D/MyApp / Map( 7446): OnStart
04-03 20:29:07.399 D/MyApp / Map( 7446): OnResume
04-03 20:29:07.432 D/MyApp / Map( 7446): Map is ready!
04-03 20:29:07.438 D/MyApp / Map( 7446): SetMapListeners
04-03 20:29:07.568 D/MyApp / Map( 7446): Camera is idle.
04-03 20:29:09.231 D/MyApp / Map( 7446): Camera move started.
04-03 20:29:09.590 D/MyApp / Map( 7446): Camera is idle.
04-03 20:29:12.350 D/MyApp / Map( 7446): Camera move started.
04-03 20:29:12.751 D/MyApp / Map( 7446): Camera is idle.

## Listeners are responding, now rotating the device.

04-03 20:29:15.503 D/MyApp / Map( 7446): OnPause
04-03 20:29:15.508 D/MyApp / Map( 7446): OnStop
04-03 20:29:15.572 D/MyApp / Map( 7446): OnDestroy
04-03 20:29:15.595 I/Google Maps Android API( 7446): Google Play services package version: 10298438
04-03 20:29:15.596 D/MyApp / Map( 7446): OnCreate
04-03 20:29:15.628 I/Google Maps Android API( 7446): Google Play services package version: 10298438
04-03 20:29:15.655 D/MyApp / Map( 7446): OnStart
04-03 20:29:15.655 D/MyApp / Map( 7446): OnResume
04-03 20:29:15.690 D/MyApp / Map( 7446): Map is ready!
04-03 20:29:15.691 D/MyApp / Map( 7446): SetMapListeners

## Map is rotated, camera position was preserved. 
## Now moving the camera, but no listeners are responding.

04-03 20:29:24.436 D/MyApp / Map( 7446): OnPause
04-03 20:29:31.288 D/MyApp / Map( 7446): OnStop
04-03 20:29:31.359 D/MyApp / Map( 7446): OnDestroy

对我来说有趣的是,当我切换回之前的 activity 并再次打开地图时,它会重新开始并再次运行。但是,正如您在日志中看到的那样,在旋转设备时,activity 也被销毁并重新创建。据我所知,片段不是,所以这可能是暗示。我不知道。

我也尝试删除 OnDestroy 中的侦听器(通过设置 null),但是那也没有改变任何东西。

你知道我可能做错了什么吗?

尝试将 InitializeMap() 调用置于 OnCreateView() 方法的覆盖中而不是 OnCreate()

默认情况下,当屏幕旋转时,您的 Activity 将被终止并重新启动。为确保没有数据丢失,您需要使用生命周期方法正确保存和恢复数据。请参阅 SavingPersistentState or savedInstanceState and Follow this Android Developer Documentation 希望这对您有所帮助。!

我遇到了类似的问题,因为我们将 MapFragment 嵌套在另一个 Fragment 中,所以我们每次都必须重新添加 MapFragment。由于您将它直接嵌入到 Activity 中,@App Pack 应该也可以,但我还是会粘贴代码。

@Override
protected void onAttachedToWindow() {
    super.onAttachedToWindow();  //onCreateView() or onResume() should work too

    FragmentManager fragmentManager = ((AppCompatActivity) getContext()).getSupportFragmentManager();
    SupportMapFragment mapFragment = SupportMapFragment.newInstance();
    fragmentManager.beginTransaction()
        .replace(R.id.mapContainer, mapFragment)
        .commit();
    mapFragment.getMapAsync(this);
}

@Override
public void onMapReady(GoogleMap googleMap) {
    this.googleMap = googleMap;

    UiSettings uiSettings = googleMap.getUiSettings();
    uiSettings.setZoomControlsEnabled(false);

    //do your initialization + recreate your last map position from BundleSavedIntance: check this answer: 
}

请注意:函数应以小写开头!!!

尝试检查 savedInstanceState 以查看您的 Activity 是否是第一次构建,或者它是否只是一个 return。您似乎在每次调用时都在重叠片段。