2010-05-17 22 views
21

ich folgende und bin ein bisschen stuck auf diese für ein paar Tage zu tun:Efficient Map Overlays in Android Google Map

  1. Ich habe versucht, zu zeichnen Polylinien (ich habe codierte Polylinien, aber habe es geschafft, diese zu entschlüsseln) die bewegen, wenn ich die Karte verschieben.
    Die einzige Lösung, die ich fand, war, dass Geopunkte in Bildschirmkoordinaten umgewandelt werden ... die sich nicht bewegen, wenn ich die Karte bewege.

  2. I used HelloItemizedOverlay hinzufügen etwa 150 Marker und es wird sehr sehr langsam.
    Irgendeine Idee, was zu tun ist? Ich dachte über Threads (Handler) nach.

  3. Ich war auf der Suche nach einer Art von Timer-Funktion, die eine bestimmte Funktion in regelmäßigen Abständen, sagen wir, alle 1 Minute oder so.

  4. ich auch nach Möglichkeiten, um klar der Google-Karte von allen Markierungen/Linien usw.

+1

q 1 gelöst ... fand ich die Antwort während des Surfens durch stackoverflow.com ... :) Die Lösung wird hier gepostet http://stackoverflow.com/questions/2176397/will-to-draw-a-line-oder-pfad-auf-google-map-in-hellomapview – Ahsan

+1

q4 ... gelöst ist, fand ich die Antwort auf stackoverflow.com ... das lösen ist: .. verwenden Dieser Code if (! mapOverlays.isEmpty()) { mapOverlays.clear(); mapView.invalidate(); } – Ahsan

+3

q2 gelöst, auf ostackoverflow.com gefunden ... ////////////////////////// createMarkers() { für (elem: bigList) { GeoPoint geoPoint = neuer GeoPoint ((int) (elem.getLat() * 1000000), (int) (elem.getLon() * 1000000)); OverlayItem overlayItem = neues OverlayItem (geoPoint, elem.getName(), elem.getData()); itemizedOverlay.addOverlay (overlayItem); } itemizedOverlay.populateNow(); mapOverlays.add (itemizedOverlay); // außerhalb der for-Schleife } und in MyOverlay: public void addOverlay (OverlayItem overlay) { m_overlays.add (Overlay); } öffentliche Leere populateNow() { populate(); } – Ahsan

Antwort

11

Antworten gegeben unten anschaute:

1) Hier ist eine Lösung, die ich verwenden :

/** Called when the activity is first created. */ 
private List<Overlay> mapOverlays; 

private Projection projection; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

    linearLayout = (LinearLayout) findViewById(R.id.zoomview); 
    mapView = (MapView) findViewById(R.id.mapview); 
    mapView.setBuiltInZoomControls(true); 

    mapOverlays = mapView.getOverlays();   
    projection = mapView.getProjection(); 
    mapOverlays.add(new MyOverlay());   

} 

@Override 
protected boolean isRouteDisplayed() { 
    return false; 
} 

class MyOverlay extends Overlay{ 

    public MyOverlay(){ 

    } 

    public void draw(Canvas canvas, MapView mapv, boolean shadow){ 
     super.draw(canvas, mapv, shadow); 

    Paint mPaint = new Paint(); 
     mPaint.setDither(true); 
     mPaint.setColor(Color.RED); 
     mPaint.setStyle(Paint.Style.FILL_AND_STROKE); 
     mPaint.setStrokeJoin(Paint.Join.ROUND); 
     mPaint.setStrokeCap(Paint.Cap.ROUND); 
     mPaint.setStrokeWidth(2); 

     GeoPoint gP1 = new GeoPoint(19240000,-99120000); 
     GeoPoint gP2 = new GeoPoint(37423157, -122085008); 

     Point p1 = new Point(); 
     Point p2 = new Point(); 

    Path path = new Path(); 

    Projection projection.toPixels(gP1, p1); 
     projection.toPixels(gP2, p2); 

     path.moveTo(p2.x, p2.y); 
     path.lineTo(p1.x,p1.y); 

     canvas.drawPath(path, mPaint); 
    } 

courtesy: Drawing a line/path on Google Maps

2) Hier ist, was für mich gearbeitet:

createMarkers() 
{ 
    for(elem:bigList) 
    { 
     GeoPoint geoPoint = new GeoPoint((int)(elem.getLat()*1000000), (int) (elem.getLon()*1000000)); 
     OverlayItem overlayItem = new OverlayItem(geoPoint, elem.getName(), elem.getData()); 
     itemizedOverlay.addOverlay(overlayItem); 
    } 

    itemizedOverlay.populateNow(); 
    mapOverlays.add(itemizedOverlay); //outside of for loop 
} 

und in MyOverlay:

public void addOverlay(OverlayItem overlay) 
{ 
    m_overlays.add(overlay); 
} 

public void populateNow() 
{ 
    populate(); 
} 

courtesy: stackoverflow.com unbekannt Link

3) Der beste Weg ist es, eine Timer-Klasse zu verwenden . Eine sehr detaillierte Beschreibung der Timer-Klasse und wie benutzt man es unter diesem Link angegeben:

http://life.csu.edu.au/java-tut/essential/threads/timer.html

4) Ich habe diesen Code:

if(!mapOverlays.isEmpty()) 
{ 
    mapOverlays.clear(); 
    mapView.invalidate(); 
} 

Hoffnung diese Antworten helfen atleast eine weitere Person . Vielen Dank.

+1

Sie sollten Ihre Lösung in einer separaten Antwort und nicht in Kommentaren bereitstellen. Es ist besser für alle und es ermöglicht Ihnen, Formatierung für den Code zu verwenden. –

+1

Sie sind der Mann. Ich hatte eine Aufgabe für das Plotten von 200/300 Pins auf der Karte, und ich hatte Probleme, keine Glätte zu haben. Während meiner F & E bin ich auf diesen Artikel gestoßen und Sie sind der Mann. Ich danke dir sehr. ** Lösung zum Plotten mehrerer Pins auf MapView ** ist Schritt-2 –

+0

@PareshMayani: Froh, dass es geholfen hat :) – Ahsan

0

Für # 2 glaube ich nicht, dass Sie dort etwas gelöst haben. Ihr schwer lesbarer Code zeigt Ihnen, wie Sie Markierungen auf die Überlagerung setzen und dann diese Überlagerung der Karte hinzufügen. Genau so mache ich es. Ich habe Karte mit ungefähr 300 Hotels und es dauert ungefähr 5 Sekunden für Android auf meinem Nexus One, um Markierungen zu schaffen. Die ganze Sache läuft innerhalb des Threads und ich denke, ich muss eine Art Fortschrittsbalken machen, um den User wissen zu lassen, was vor sich geht.

Ich arbeite an App, die bereits auf dem iPhone existiert und es scheint, dass das iPhone keine Probleme hat, diese 300+ Markierungen fast sofort zu zeichnen. Ich werde es schwer haben, meinen Chefs die Existenz eines Fortschrittsbalkens zu erklären.

Wenn jemand Ahnung hat, wie man diesen Prozess optimieren kann ... werde ich dankbar sein.

Hier ist mein Code:

... 
     for (int m = 0; m < ArrList.size(); m++) { 
      tName = ArrList.get(m).get("name").toString(); 
      tId = ArrList.get(m).get("id").toString(); 
      tLat = ArrList.get(m).get("lat").toString();; 
      tLng = ArrList.get(m).get("lng").toString();; 
      try { 
       lat = Double.parseDouble(tLat); 
       lng = Double.parseDouble(tLng); 
       p1 = new GeoPoint(
         (int) (lat * 1E6), 
         (int) (lng * 1E6)); 
       OverlayItem overlayitem = new OverlayItem(p1, tName, tId); 
       itemizedoverlay.addOverlay(overlayitem); 
      } catch (NumberFormatException e) { 
       Log.d(TAG, "NumberFormatException" + e);  
      } 
     } 

Ich weiß, dass ich durch die Vermeidung von diesem String> Doppel Umwandlung etwas Zeit sparen könnte, aber ich fühle mich nicht, dass mir erhebliche Einsparungen geben würde .. oder es würde?

2

Ich habe das gleiche Problem. Wir entwickeln zur gleichen Zeit eine iPhone App und eine Android App. Ich habe 2500 + Karten-Overlays. Kein Problem auf dem iPhone; ein riesiger Performance-Hit auf Android beim Aufruf von populate() nach dem Hinzufügen aller Overlays. (Natürlich war mein erster Versuch, populate() jedes Mal nach dem Hinzufügen eines Overlays aufzurufen, ein typischer Fehler aufgrund von googles Tutorial. Jetzt rufe ich populate() nur einmal auf, nachdem alle 2500+ Overlays zum ItemizedOverlay hinzugefügt wurden.)

So dauert der einzelne populate() Aufruf über 40 Sekunden auf einem HTC Hero-Gerät abzuschließen. Ich musste ein beschäftigtes Zeichen setzen; Es ist kein Fortschrittsbalken möglich, da wir keine Informationen über den Fortschritt von populate() erhalten können.

Ich habe eine andere Lösung versucht: Verwenden Sie nicht ItemizedOverlay, sondern fügen Sie Overlays von Hand hinzu, Unterklasse Overlay. Ergebnis: In der Tat ist es viel schneller, alle diese Überlagerungen zur Karte hinzuzufügen; Die Map wird jedoch aufgrund des konstanten Aufrufs der draw() - Methode für jedes Overlay unbrauchbar. In meiner Draw-Methode habe ich versucht, so viel wie möglich zu optimieren; Ich erstelle nicht jedes Mal eine Bitmap. Meine draw() - Methode sieht folgendermaßen aus:

public void draw(android.graphics.Canvas canvas, MapView mapView, boolean shadow) { 
// our marker bitmap already includes shadow. 
// centerPoint is the geopoint where we need to put the marker. 
if (!shadow) { 
    Point point = new Point(); 
    mapView.getProjection().toPixels(centerPoint, point); 
    canvas.drawBitmap(markerBitmap, point.x, point.y, null); 
} 

} 

Hier ist markerBitmap vorberechnet. Ich weiß nicht, was ich noch optimieren könnte. Ist eine Art von populate() Call erforderlich, wenn wir ItemizedOverlay nicht verwenden ??? Ich konnte dafür keine guten Antworten finden.

Momentan speichere ich das ItemizedOverlay, sobald es in einem Hintergrundthread erstellt wurde. Auf diese Weise muss der Benutzer nicht jedes Mal warten.

+0

+1 für detaillierte Erklärung. –

+0

Das Hinzufügen von 2500 Markern ist auf Android praktisch unmöglich. Die Lösung in diesem Projekt bestand zum einen darin, die auf dem aktuellen Teil der Karte sichtbaren Markierungen zu finden. (Dies muss jedes Mal nach dem Schwenken/Zoomen neu berechnet werden.) Dann prüfen wir, ob <100 Marker vorhanden sind, andernfalls müssen nicht alle angezeigt werden. Die 100 Marker können innerhalb weniger Sekunden zu einer Karte hinzugefügt werden. All dies befindet sich natürlich in einem Hintergrund-Thread, so dass der Benutzer einen rotierenden Kreis betrachtet, während wir darauf warten, dass populate() beendet wird. Auf dem iPhone ist der analoge Code augenblicklich (2500 Marker waren auch ein bisschen langsam). – winitzki

-3

Eine Anzahl von Zeichenobjekten kann zu einem einzelnen Overlay hinzugefügt werden, das dann zur Karte hinzugefügt werden kann. Daher wäre das Zeichnen einer x Anzahl von Überlagerungen für eine x Anzahl von Objekten nicht notwendig, außer wenn die Objekte von unterschiedlichen Typen sind. Code-Schnipsel .. .. Hier CustomPinPoint ist meine Klasse, die ItemizedOverlay<OverlayItem>

CustomPinPoint customPinPoint = new CustomPinPoint(drawable, Main.this); 

OverlayItem tempOverLayItem = new OverlayItem(
    touchedPoint, "PinPoint", "PintPoint 2"); //Point One 
customPinPoint.insertPinPoint(tempOverLayItem); 
tempOverLayItem = new OverlayItem(new GeoPoint(
     (int)(-27.34498 * 1E6), (int)(153.00724 * 1E6)), "PinPoint", 
    "PintPoint 2"); //Point Two 
customPinPoint.insertPinPoint(tempOverLayItem); 
overlayList.add(customPinPoint); //Overlay added only once 
-2

Für Ihre vierte Frage erweitert .... einfach die mapOverlays.clear verwenden(); Methode und alle vorherigen Marker werden verschwinden.

Code:

if(!mapOverlays.isEmpty()) { 
    mapOverlays.clear(); 
    mapView.invalidate(); 
}