Как сохранить/переупорядочить прослушиватели событий на MapFragment после поворота устройства (портрет/пейзаж)?

Я разрабатываю приложение для Android с Xamarin (версия 7.1). Он отображается как карта и рисует PolyLines, делая это в OnCameraIdle().

MapFragment создается программно в OnCreate. Я извлекаю GoogleMap в OnResume через GetMapAsync и привязывая слушателей в 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

Интересная вещь для меня заключается в том, что когда я возвращаюсь к предыдущему действию и снова открываю карту, она начинает новую работу и снова работает. Однако, как вы видите в журнале, при вращении устройства, активность также уничтожается и создается заново. Насколько мне известно, фрагмента нет, возможно, это намек. Я не знаю.

Я также попытался удалить слушателей в OnDestroy (установив null), но это тоже ничего не изменило.

У вас есть представление, что я могу делать неправильно?

Ответ 1

Попробуйте проверить savedInstanceState, чтобы увидеть, будет ли ваша активность создаваться в первый раз или если это просто возврат к ней. Кажется, что вы перекрываете фрагменты при каждом вызове.

Ответ 2

Попробуйте поместить вызов InitializeMap() в переопределение метода OnCreateView() вместо OnCreate()

Ответ 3

По умолчанию, когда экран повернут, ваша активность будет убита и перезапущена. Чтобы убедиться, что данные не потеряны, вам необходимо правильно сохранить и восстановить свои данные с помощью методов жизненного цикла. См. SavingPersistentState или savedInstanceState и выполните следующие действия Документация разработчика для Android Надежда Это май помогает.!

Ответ 4

У меня были подобные проблемы, потому что у нас есть MapFragment, вложенный в другой фрагмент, поэтому мы должны повторно добавлять 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: http://stackoverflow.com/info/16697891/google-maps-android-api-v2-restoring-map-state/16698624#16698624
}

И, пожалуйста: функции должны начинаться с нижнего регистра!!!