2010-03-31 8 views
14

Ich habe eine relativ einfache MapActivity, die ich versuche, eine Liste von "Lagern" innerhalb einer bestimmten Kartenregion anzuzeigen. Ich habe eine benutzerdefinierte Unterklasse von OverlayItem namens CampOverlayItem, eine benutzerdefinierte ItemizedOverlay namens CampsOverlay, die CampOverlayItems zurückgibt, und natürlich eine MapActivity-Unterklasse, die die Karte füllt.NullPointerException in ItemizedOverlay.getIndexToDraw

Ich ziehe die Overlay-Daten aus einer Datenbank mit einer AsyncTask wie erstellt in meiner Aktivität. Die AsyncTask wird von einem ViewTreeObserver.OnGlobalLayoutListener ausgelöst, der an MapView angehängt ist.

Im OnPostExecute Methode des AsyncTask, erstelle ich eine neue Instanz meiner CampsOverlay Klasse und eine Liste der von die Datenbank zurückLager passieren (die in doInBackground abgerufen werden). Ich rufe dann an:

mapView.getOverlays().add(newOverlay); 

wo newOverlay das CampsOverlay ist, das ich gerade erstellt habe. All dieses Codes läuft ohne Fehler, aber wenn die Karte selbst zu zeichnen versucht, erhalte ich ein Nullpointer mit dem folgenden Stack-Trace:

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) 

Weil es besonders wichtig scheint, hier ist der Code für meine ItemizedOverlay Unterklasse:

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(); 
    } 

} 

Hat jemand eine Idee, was hier passieren könnte? Ich habe versucht, zu überprüfen, dass alles, was ich Kontrolle habe, nicht null ist. Ich kann mehr Code bei Bedarf bereitstellen.

Antwort

20

Ich sehe nicht, wo Sie populate() auf Ihrem CampsOverlay anrufen.

Here is a sample project zeigt asynchrones Laden von Overlay-Elementen - vielleicht wird es Ihnen einige Ideen geben, wenn populate() nicht das Problem ist.

+0

Sie sind völlig richtig, danke Mark. Sie würden denken, ich hätte Ihren Beispielcode genauer untersucht, bevor Sie diese Frage gestellt haben. Jetzt muss ich nur herausfinden, warum die Overlay-Elemente nicht erscheinen;) – lyricsboy

3

Er hat Recht. Sie müssen populate() aufrufen, um das Overlay zu füllen. Sie möchten möglicherweise alle Overlay-Elemente im Konstruktor erstellen, populate aufrufen und in createItem das Element einfach aus einer Liste zurückgeben.

+0

Hat es einen Vorteil, die Elemente im Konstruktor statt einzeln in createItem zu erstellen?Nach dem Lesen der Dokumentation speichert ItemizedOverlay die Ergebnisse von createItem zwischen, so dass es nicht unbedingt notwendig ist, sich an die in meiner Unterklasse zu halten. – lyricsboy

2

„Jetzt muss ich nur noch herausfinden, warum die Overlay-Elemente nicht erscheinen“

Falls Sie nicht, es ist, weil Sie eine statische Funktion auf Ihrem Drawable verwenden haben, die erklären, wie ist Ihr Marker positioniert.

können Sie diese verwenden, in Ihrem CampsOverlay Konstruktor:

super(boundCenter(defaultMarker));

Dies, dass der Ursprung Ihres Drawable das Zentrum anzeigt. Sie können auch boundCenterBottom() verwenden, um anzugeben, dass der Ursprung die untere Mitte der Drawable ist.