Android Maps v2 MapView intérieur fragment personnalisé (NPE)

Je ne veux pas utiliser ou étendre SupportMapFragment ou MapFragment. J'ai ma propre classe de base avec un tas de code.

La documentation indique clairement que lorsque quelqu'un utilise MapView par lui-même, toutes les méthodes de cycle de vie correspondantes(onCreate() onResume() etc.) doit être appelée.

La plupart des méthodes de cycle de vie dans un {[5] } sont similaires à un Activity mais quand je commute entre mes Fragment, je finis par obtenir un NPE obscurci dans onDestroy() ou dans onResume() méthodes.

Tous les échantillons à condition d'utiliser un Activity avec MapView, mais n'est pas coutume Fragment.

Quelqu'un A déjà fait? Pouvez-vous fournir un exemple de code d'un MapView dans votre propre Fragmentclasse?

22
demandé sur dnkoutso 2012-12-11 07:01:28

3 réponses

J'ai réussi à inclure un MapView (v2) dans un Fragment personnalisé lui-même intégré dans un ViewPager. Dans mon cas, MapView est inclus dans le fichier de mise en page de fragments. J'ai dû appeler des méthodes de cycle de vie sur MapView (onCreate() appelé onCreateView() à partir du Fragment), et appeler manuellement MapsInitializer.initialize(context) pour éviter un NullPointerException de la classe BitmapDescriptorFactory (pour obtenir le bitmap pour les marqueurs). Cette dernière astuce est étrange, et je ne sais pas pourquoi la Carte n'est pas correctement initialisé sans cet appel, peut-être que c'est juste un bug dans la version actuelle ...

Dans mon cas, je n'ai pas eu de NullPointerException dans onResume() ou onDestroy().

13
répondu PoPy 2012-12-11 17:25:19

J'ai un peu lutté avec la réponse de PoPy mais à la fin je l'ai réussi et voici ce que j'ai trouvé. Probablement cela est utile à d'autres qui rencontreront également ce problème:

public class MyMapFragment extends Fragment {

    private MapView mMapView;
    private GoogleMap mMap;
    private Bundle mBundle;

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

        try {
            MapsInitializer.initialize(getActivity());
        } catch (GooglePlayServicesNotAvailableException e) {
            // TODO handle this situation
        }

        mMapView = (MapView) inflatedView.findViewById(R.id.map);
        mMapView.onCreate(mBundle);
        setUpMapIfNeeded(inflatedView);

        return inflatedView;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBundle = savedInstanceState;
    }

    private void setUpMapIfNeeded(View inflatedView) {
        if (mMap == null) {
            mMap = ((MapView) inflatedView.findViewById(R.id.map)).getMap();
            if (mMap != null) {
                setUpMap();
            }
        }
    }

    private void setUpMap() {
        mMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker"));
    }

    @Override
    public void onResume() {
        super.onResume();
        mMapView.onResume();
    }

    @Override
    public void onPause() {
        super.onPause();
        mMapView.onPause();
    }

    @Override
    public void onDestroy() {
        mMapView.onDestroy();
        super.onDestroy();
    }
}

Et voici le res/layout/map_fragment.xml correspondant:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <com.google.android.gms.maps.MapView
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</RelativeLayout>

Vous pouvez omettre le RelativeLayout (et déplacer la déclaration xmlns vers votre nouvel élément racine, dans ce cas le com.google.android.gms.maps.MapView) Si vous n'avez qu'un seul élément dans votre mise en page comme dans cet exemple.

35
répondu Jens Kohl 2013-01-03 13:29:15

Tout en utilisant un MapView séparé suivant deux choses sont d'une importance vitale

    //at Activity
    @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      MapsInitializer.initialize(this);
      mapView.onCreate(savedInstanceState); 
    }
    //or at Fragment
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
                       Bundle savedInstanceState) {

       MapsInitializer.initialize(getActivity());  
       mapView.onCreate(mBundle);
     }
    //along with the following
    @Override
    protected void onResume() {
       super.onResume();
       if (mapView != null)
        mapView.onResume();
      }

    @Override
    protected void onDestroy() {
       super.onDestroy();
       if (mapView != null)
        mapView.onDestroy();
    }

    @Override
    public void onLowMemory() {
      super.onLowMemory();
      if (mapView != null)
        mapView.onLowMemory();
    }
-2
répondu laaptu 2014-06-19 07:13:17