Comment mettre en cache android.graphics.path ou Bitmap lors de l'utilisation de superpositions?

J'utilise une superposition pour marquer les zones sur Google Maps en dessinant une forme de dix milles de GeoPoints que je reçois d'une source quelconque. Cela fonctionne et ressemble à ceci:

@Override public void draw(android.graphics.Canvas canvas, MapView mapView, boolean shadow) { super.draw(canvas, mapView, false); Projection projection = mapView.getProjection(); List<Zone> zones = ApplicationContext.getZones(); path.rewind(); for (Zone zone : zones) { paint.setDither(true); paint.setStyle(Style.FILL); paint.setAlpha(40); MultiPolygon multiPolygon = zone.getMultiPolygon(); List<Polygon> polygons = multiPolygon.getPolygons(); for (Polygon polygon : polygons) { for (List<Coordinate> coordinates : polygon.getCoordinates()) { for (int i = 0; i < coordinates.size(); i++) { Point p = new Point(); projection.toPixels(new GeoPoint((int)(coordinates.get(i).getLatitude() * 1E6), (int)(coordinates.get(i).getLongitude() * 1E6)), p); if (i == 0) { path.moveTo(px, py); } else { path.lineTo(px, py); } } } } } canvas.drawPath(path, paint); } 

Le problème, c'est que cela prend beaucoup de ressources. Chaque fois que l'on fait défiler ou déplacer la carte sur MapView, le chemin d'accès doit être calculé à plusieurs reprises, car les coordonnées des pixels ont été modifiées. La zone dessinée pourrait devenir si grande que le défilement sur MapView est si lent qu'il est inutilisable.

  • Portrait ou paysage Android
  • DisplayListCanvas est démarré sur RenderNode non bloqué (sans mOwningView)
  • LoaderManager.restartLoader () entraînera-t-il toujours un appel sur onCreateLoader ()?
  • JNI en gardant une référence globale à un objet, en l'accédant avec d'autres méthodes JNI. Garder un objet C ++ vivant sur plusieurs appels JNI
  • Comment souligner un texte dans android xml?
  • JSOUP sélectionnez <div> avec ID spécifique
  • Mes idées sont

    • De manière concrète, cache la "forme" générée par le chemin et redessinez-le lorsque le niveau de zoom change sur MapView.
    • Pour dessiner le tableau d'une manière "à la volée" -Bitmap pour l'utiliser comme Overlay (peut-être comme ItemizedOverlay), écouter le défilement MapView et déplacer le bitmap par la distance défilée.

    Je ne sais pas s'il existe de meilleures méthodes.

    Des idées sur la façon dont je pourrais résoudre ce problème? (J'utilise Google Maps API 1 et je ne peux pas changer).

  • Tâche Gradle Javadoc sans avertissement
  • Comment ajouter par programme un élément de sous-menu à la nouvelle bibliothèque de support de support de matériel
  • Cordova File Plugin - Lire dans le dossier www?
  • Greenbot Eventbus 3.0: quelle est la différence entre onEvent, onEventMainThread, onEventBackgroundThread et onEventAsync?
  • Couleur des ombres sur les boutons selon l'état en XML - Android
  • DemandeFocus sautant ensuite EditText
  • 2 Solutions collect form web for “Comment mettre en cache android.graphics.path ou Bitmap lors de l'utilisation de superpositions?”

    Avant de recourir à essayer de déterminer comment faire correspondre le mouvement de la carte, il existe des optimisations pour votre code actuel qui générera probablement des économies importantes. En particulier, ces deux lignes à l'intérieur de votre boucle intérieure sont exécutées le plus souvent, mais assez coûteuses à exécuter (deux allocations de mémoire, multiplication par virgule flottante et quatre appels de méthode).

     Point p = new Point(); projection.toPixels(new GeoPoint((int)(coordinates.get(i).getLatitude() * 1E6), (int)(coordinates.get(i).getLongitude() * 1E6)), p); 

    D'abord, vous avez seulement besoin d'un objet Point , alors évitez de l'attribuer dans votre boucle. Déplacez-le juste au-dessous de votre path.rewind();

    Deuxièmement, si vous avez pré-calculé vos coordonnées en tant que GeoPoints au lieu de les calculer à chaque fois, vous économisriez beaucoup de traitement dans votre routine de draw . Vous pouvez également vous débarrasser de cette déclaration if avec un peu de travail. En supposant que vous préconvertissez votre liste de coordinate dans une liste de GeoPoint , et rendez-la disponible via polygon.getGeoCoordinates() , vous pourriez vous retrouver avec vos boucles internes qui ressemblent à –

     for (List<GeoPoint> geoCoordinates : polygon.getGeoCoordinates()) { projection.toPixels(geoCoordinates.get(0),p); path.moveTo(px, py); // move to first spot final List<GeoPoint> lineToList = geoCoordinates.sublist(1,geoCoordinates.size()); // A list of all the other points for(GeoPoint gp : lineToList) { projection.toPixels(gp, p); path.lineTo(px, py); } } 

    Et cela fonctionnera beaucoup plus vite que ce que vous aviez fait auparavant.

    Après avoir brisé les derniers jours, j'ai trouvé une solution possible (et je ne pense pas qu'il y en a une meilleure) pour ne pas dessiner le chemin encore et encore, mais la déplacer vers la position actuelle.

    La partie difficile était de savoir comment mettre en cache la forme dessinée pour ne pas la calculer encore et encore. Cela peut se faire en utilisant une Matrice. Avec cette matrice (j'imagine cela comme une sorte de "modèle"), vous pouvez manipuler les coordonnées des points dans le chemin. La première fois (quand quelqu'un commence à déplacer la carte), je dessine la zone comme d'habitude. Quand il essaie de le calculer la deuxième fois ou plus, je ne redessine pas la forme, mais je manipule le chemin en calculant le "delta" du point actuel au dernier point. Je sais quel est le point actuel, car je mapple toujours le GeoPoint original (qui reste toujours le même) au point qui résulte de la projection actuelle. Le "delta" doit être défini comme Matrix. Ensuite, je transforme le chemin en utilisant cette nouvelle Matrice. Le résultat est vraiment très rapide. Le défilement de la carte est aussi rapide que sans utiliser une superposition.

    Cela ressemble à ceci (ce n'est pas un code de production, et il ne peut pas encore traiter le zoom, mais il montre le principe que j'utilise comme base pour mes optimisations):

     public class DistrictOverlay extends Overlay { // private final static String TAG = DistrictOverlay.class.getSimpleName(); private Paint paint = new Paint(); private Path path = new Path(); private boolean alreadyDrawn = false; private GeoPoint origGeoPoint; Point p = new Point(); Point lastPoint = new Point(); @Override public void draw(android.graphics.Canvas canvas, MapView mapView, boolean shadow) { super.draw(canvas, mapView, false); Projection projection = mapView.getProjection(); List<Zone> zones = ApplicationContext.getZones(); if (!alreadyDrawn) { path.rewind(); for (Zone zone : zones) { if (!zone.getZoneId().equals(MenuContext.getChosenZoneId())) { continue; } String dateString = zone.getEffectiveFrom().trim().replace("CEST", "").replace("GMT", "").replace("CET", "").replace("MESZ", ""); if (DateUtil.isBeforeCurrentDate(dateString)) { paint.setColor(Color.RED); } else { paint.setColor(Color.GREEN); } paint.setDither(true); paint.setStyle(Style.FILL); paint.setAlpha(40); MultiPolygon multiPolygon = zone.getMultiPolygon(); List<Polygon> polygons = multiPolygon.getPolygons(); for (Polygon polygon : polygons) { for (List<GeoPoint> geoPoints : polygon.getGeoPoints()) { projection.toPixels(geoPoints.get(0), p); path.moveTo(px, py); origGeoPoint = new GeoPoint(geoPoints.get(0).getLatitudeE6(), geoPoints.get(0).getLongitudeE6()); lastPoint = new Point(px, py); final List<GeoPoint> pathAsList = geoPoints.subList(1, geoPoints.size()); for (GeoPoint geoPoint : pathAsList) { projection.toPixels(geoPoint, p); path.lineTo(px, py); } } } } } else { projection.toPixels(origGeoPoint, p); Matrix translateMatrix = new Matrix(); translateMatrix.setTranslate(px - lastPoint.x, py - lastPoint.y); path.transform(translateMatrix); lastPoint = new Point(px, py); } canvas.drawPath(path, paint); if (!path.isEmpty()) { alreadyDrawn = true; } } @Override public boolean onTap(GeoPoint p, MapView mapView) { return true; } } 
    coAndroid est un fan Android de Google, tout sur les téléphones Android, Android Wear, Android Dev et Android Games Apps.