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 Fragment
classe?
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()
.
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.
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();
}