2010-03-31 4 views
14

J'ai une MapActivity relativement simple que j'essaie de faire afficher une liste de "camps" dans une région de carte donnée. J'ai créé une sous-classe personnalisée de OverlayItem appelée CampOverlayItem, une ItemizedOverlay personnalisée appelée CampsOverlay qui retourne CampOverlayItems, et bien sûr une sous-classe MapActivity qui remplit la carte.NullPointerException dans ItemizedOverlay.getIndexToDraw

Je tire les données de superposition d'une base de données en utilisant un AsyncTask comme créé dans mon activité. La tâche asynchrone est déclenchée à partir d'un ViewTreeObserver.OnGlobalLayoutListener attaché à MapView.

Dans la méthode onPostExecute du AsyncTask, je crée une nouvelle instance de ma classe CampsOverlay et le transmettre une liste des camps retournés de la base de données (qui sont récupérés dans doInBackground). Je demande alors:

mapView.getOverlays().add(newOverlay); 

où newOverlay est le CampsOverlay que je viens de créer. Tout ce code fonctionne sans erreur, mais lorsque la carte tente de se dessiner, je reçois un NullPointerException avec la trace de pile suivante:

java.lang.NullPointerException 
    at 
com.google.android.maps.ItemizedOverlay.getIndexToDraw(ItemizedOverlay.java: 
211) 
    at 
com.google.android.maps.ItemizedOverlay.draw(ItemizedOverlay.java:240) 
    at com.google.android.maps.Overlay.draw(Overlay.java:179) 
    at com.google.android.maps.OverlayBundle.draw(OverlayBundle.java: 
42) 
    at com.google.android.maps.MapView.onDraw(MapView.java:476) 
    at android.view.View.draw(View.java:6274) 
    at android.view.ViewGroup.drawChild(ViewGroup.java:1526) 
    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1256) 
    at android.view.ViewGroup.drawChild(ViewGroup.java:1524) 
    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1256) 
    at android.view.View.draw(View.java:6277) 
    at android.widget.FrameLayout.draw(FrameLayout.java:352) 
    at android.view.ViewGroup.drawChild(ViewGroup.java:1526) 
    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1256) 
    at android.view.ViewGroup.drawChild(ViewGroup.java:1524) 
    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1256) 
    at android.view.ViewGroup.drawChild(ViewGroup.java:1524) 
    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1256) 
    at android.view.ViewGroup.drawChild(ViewGroup.java:1524) 
    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1256) 
    at android.view.ViewGroup.drawChild(ViewGroup.java:1524) 
    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1256) 
    at android.view.View.draw(View.java:6277) 
    at android.widget.FrameLayout.draw(FrameLayout.java:352) 
    at android.view.ViewGroup.drawChild(ViewGroup.java:1526) 
    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1256) 
    at android.view.View.draw(View.java:6277) 
    at android.widget.FrameLayout.draw(FrameLayout.java:352) 
    at com.android.internal.policy.impl.PhoneWindow 
$DecorView.draw(PhoneWindow.java:1883) 
    at android.view.ViewRoot.draw(ViewRoot.java:1332) 
    at android.view.ViewRoot.performTraversals(ViewRoot.java:1097) 
    at android.view.ViewRoot.handleMessage(ViewRoot.java:1613) 
    at android.os.Handler.dispatchMessage(Handler.java:99) 
    at android.os.Looper.loop(Looper.java:123) 
    at android.app.ActivityThread.main(ActivityThread.java:4203) 
    at java.lang.reflect.Method.invokeNative(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:521) 
    at com.android.internal.os.ZygoteInit 
$MethodAndArgsCaller.run(ZygoteInit.java:791) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:549) 
    at dalvik.system.NativeStart.main(Native Method) 

Parce qu'il semble particulièrement pertinent, voici le code pour mon ItemizedOverlay Sous-classe:

public class CampsOverlay extends ItemizedOverlay<CampOverlayItem> { 
    private ArrayList<Camp> camps = null; 

    public CampsOverlay(Drawable defaultMarker, ArrayList<Camp> theCamps) 
{ 
     super(defaultMarker); 
     this.camps = theCamps; 
    } 

    @Override 
    protected CampOverlayItem createItem(int i) { 
     Camp camp = camps.get(i); 
     CampOverlayItem item = new CampOverlayItem(camp); 
     return item; 
    } 

    @Override 
    protected boolean onTap(int index) { 
     // TODO Auto-generated method stub 
     return super.onTap(index); 
    } 

    @Override 
    public int size() { 
     return camps.size(); 
    } 

} 

quelqu'un at-il une idée de ce qui pourrait se passer ici? J'ai essayé pour vérifier que tout ce que j'ai le contrôle est non nul. Je peux fournir plus de code si nécessaire.

Répondre

20

Je ne vois pas où vous appelez populate() sur votre CampsOverlay.

Here is a sample projectHere is a sample project montrant le chargement asynchrone d'éléments de surimpression - peut-être vous donnera-t-il quelques idées, si populate() n'est pas le problème.

+0

Vous avez tout à fait raison, merci Mark. Vous penseriez que j'aurais regardé plus dur à votre code d'exemple avant de poser cette question. Maintenant, je dois juste comprendre pourquoi les éléments de superposition n'apparaissent pas;) – lyricsboy

3

Il a raison. Vous devez appeler populate() pour remplir la superposition. Vous pouvez créer tous les éléments de superposition dans le constructeur, appeler populate, et dans createItem retourner simplement l'élément d'une liste.

+0

Y at-il un avantage à créer les éléments dans le constructeur au lieu d'un à la fois dans createItem?De ma lecture de la documentation, ItemizedOverlay mettra en cache les résultats de createItem, il n'y a donc pas nécessairement besoin de se raccrocher à ceux de ma sous-classe. – lyricsboy

2

« Maintenant, je dois juste comprendre pourquoi les éléments de recouvrement n'apparaissent pas »

Si vous n'avez pas, il est parce que vous devez utiliser une fonction statique sur votre Drawable qui vous expliquera comment est votre marqueur positionné.

Vous pouvez utiliser, dans votre constructeur CampsOverlay:

super(boundCenter(defaultMarker));

Ceci indique que l'origine de votre Drawable est le centre. Vous pouvez également utiliser boundCenterBottom() pour indiquer que l'origine est le centre inférieur du Drawable.

Questions connexes