Значок поиска GPS никогда не исчезает на сохраненном фрагменте в Android с помощью MyLocationOverlay (osmdroid)

Это ситуация:

У меня есть действие с PagerAdapter, содержащим три фрагмента. Это действие позволяет изменить ориентацию экрана.

Один из этих фрагментов имеет mapView, созданный с помощью библиотеки osmdroid, и этот фрагмент сохраняется (setRetainInstance(true)). При каждом изменении ориентации событие onCreateView запускается снова:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    fragmentView = (LinearLayout) inflater.inflate(R.layout.main,
            container, false);

    mapView = (MapView) fragmentView.findViewById(R.id.practice_mapview);

    mapView.setBuiltInZoomControls(true);
    mapView.setMultiTouchControls(true);
    mapView.setTileSource(TileSourceFactory.MAPNIK);
    mapView.setUseSafeCanvas(true);
    setHardwareAccelerationOff();

    mapController = (MapController) mapView.getController();

    [...]

    mLocationOverlay = new MyLocationOverlay(getActivity(), mapView);
    mLocationOverlay.setDrawAccuracyEnabled(true);

    [...]

    mapView.invalidate();

    return fragmentView;
}

При запуске все работает нормально, но когда я поворачиваю телефон, снова выполняется предложение "mLocationOverlay = new MyLocationOverlay(getActivity(), mapView);", а это значит, что при закрытии приложения значок GPS никогда не исчезает.

Если не поворачивать телефон, значок исчезает при закрытии приложения.

Это то, что у меня есть в событии onPause:

@Override
public void onPause() {
    mLocationOverlay.disableCompass();

    if (this.getActivity().isFinishing()) {
        disableMyLocation();    
        releaseLocationOverlay();
    }

    cleanMapViewCache();
}

private void disableMyLocation() {
    if (mLocationOverlay.isMyLocationEnabled() == true)
        mLocationOverlay.disableMyLocation();

    if (mLocationOverlay.isFollowLocationEnabled() == true)
        mLocationOverlay.disableFollowLocation();
}

private void releaseLocationOverlay() {
    if (mLocationOverlay != null) {
        mapView.getOverlays().remove(mLocationOverlay);
        mLocationOverlay = null;
    }
}

private void cleanMapViewCache() {
    mapView.getTileProvider().clearTileCache();
    System.gc();
}

В событии onCreateView есть контроль над исчезновением проблемы:

Если я помещу этот элемент управления в событие onCreateView, проблема исчезнет:

if (this.getActivity().isFinishing())
    mLocationOverlay = new MyLocationOverlay(getActivity(), mapView);

Но тогда, среди прочего, я больше не могу центрироваться:

mapController.animateTo(mLocationOverlay.getMyLocation());

Есть идеи? Я что-то делаю не так?

Если вам нужно больше кода, вам больше нечего сказать. Благодарю вас!


person Requete    schedule 21.07.2014    source источник


Ответы (1)


Две вещи здесь:

1) Насколько я понимаю ваш код, mLocationOverlay воссоздается при изменении ориентации, но без отключения его старого экземпляра, в результате чего LocationListener остается активным и связанным с GPS.

Вместо этого в onCreate():

// this is a copypaste of your workaround code but that prevents the map from moving
if (this.getActivity().isFinishing())
    mLocationOverlay = new MyLocationOverlay(getActivity(), mapView);

попробуйте сделать:

if (mLocationOverlay != null) {
    uninitialize(); // see below
    mLocationOverlay = new MyLocationOverlay(getActivity(), mapView);
 }

а затем измените свой onPause() таким образом:

public void onPause() {
    uninitialize();
}

и создайте этот метод:

private void uninitialize() {
    // What follows is your former onPause() code:
    mLocationOverlay.disableCompass();

    if (this.getActivity().isFinishing()) {
        disableMyLocation();    
        releaseLocationOverlay();
    }

    cleanMapViewCache();
}

Все это подлежит оптимизации/рефакторингу. Я не уверен, что вызов cleanMapViewCache() при изменении ориентации устройства полезен, например.

2) Также, очень важно, не переводите свой прежний mapController из одной ориентации в другую: поскольку ваш MapView повторно инициализируется в onCreate(), ваш контроллер также должен быть повторно инициализирован. Вероятно, поэтому карта больше не движется: контроллер обращается к предыдущему экземпляру этого MapView вместо текущего.

Все это работает? Не стесняйтесь, дайте мне знать, я отредактирую свой ответ, если это необходимо.

person Shlublu    schedule 22.07.2014