ich habe ein großes speicherproblem in meiner app. Ich benutze Google Map API v2 mit ClusterManager
und benutzerdefinierte Markierungen. Ich gebe ein Bild per Anruf an markerOptions.icon(BitmapDescriptorFactory.fromBitmap(bitmap));
für jeden Marker basierend auf seiner Kategorie. das Problem ist: nach mehreren Drehungen Bildschirm meiner App abstürzt wegen OOM-Fehler:google maps api v2 aus speicherfehler
05-14 11:04:12.692 14020-30201/rokask.rideabike E/art﹕ Throwing OutOfMemoryError "Failed to allocate a 4194316 byte allocation with 1627608 free bytes and 1589KB until OOM"
05-14 11:04:12.722 14020-30201/rokask.rideabike E/AndroidRuntime﹕ FATAL EXCEPTION: GLThread 19179
Process: rokask.rideabike, PID: 14020
java.lang.OutOfMemoryError: Failed to allocate a 4194316 byte allocation with 1627608 free bytes and 1589KB until OOM
at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
at android.graphics.Bitmap.nativeCreate(Native Method)
at android.graphics.Bitmap.createBitmap(Bitmap.java:939)
at android.graphics.Bitmap.createBitmap(Bitmap.java:912)
at android.graphics.Bitmap.createBitmap(Bitmap.java:879)
at com.google.maps.api.android.lib6.gmm6.n.c.i.a(Unknown Source)
at com.google.maps.api.android.lib6.gmm6.n.c.l.a(Unknown Source)
at com.google.maps.api.android.lib6.gmm6.n.c.l.a(Unknown Source)
at com.google.maps.api.android.lib6.gmm6.n.c.l.b(Unknown Source)
at com.google.maps.api.android.lib6.gmm6.n.c.b.ak.a(Unknown Source)
at com.google.maps.api.android.lib6.gmm6.n.c.b.as.a(Unknown Source)
at com.google.maps.api.android.lib6.gmm6.n.x.a(Unknown Source)
at com.google.maps.api.android.lib6.gmm6.n.l.a(Unknown Source)
at com.google.maps.api.android.lib6.gmm6.n.l.b(Unknown Source)
at com.google.maps.api.android.lib6.gmm6.n.cv.f(Unknown Source)
at com.google.maps.api.android.lib6.gmm6.n.cv.run(Unknown Source)
ich habe ein LruCache
Objekt mit meinem Bitmap
s, es bedeutet, dass ich sie nicht neu, aber sie wiederzuverwenden. Ich kann klar sehen, dass jedes Bitmap
Objekt aus dem Cache, nicht von anderswo genommen wird. Wenn die Bitmap
jedoch noch nicht im Cache ist (beim ersten Laden), lade ich sie aus dem internen Speicher meiner App, aber es funktioniert nur, wenn die Bitmap
das erste Mal gestartet wird. Ich behalte die Instanz der LruCache
in einer beibehaltenen Fragment
Instanz und übergeben Sie es an meine benutzerdefinierte DefaultClusterRenderer<MyObject>
Objekt jedes Mal, wenn die Activity
neu erstellt wird und Karte neu gezeichnet werden muss.
das ist mein DefaultClusterRenderer<MyItem>
Erweiterung:
public class DotRenderer extends DefaultClusterRenderer<Dot> {
private final String internalStorageDir;
private final LruCache<String, Bitmap> lruCache;
public DotRenderer(Context context, GoogleMap googleMap, ClusterManager<Dot> clusterManager,
LruCache<String, Bitmap> lruCache, String internalStorageDir)
{
super(context, googleMap, clusterManager);
//this.bitmaps = bitmaps;
this.internalStorageDir = internalStorageDir;
this.lruCache = lruCache;
}
@Override
protected void onBeforeClusterItemRendered(Dot mapObject, MarkerOptions markerOptions) {
markerOptions.title(mapObject.getTitle());
String id = Integer.toString(mapObject.getTypeId());
//
Bitmap bitmap = getBitmapFromMemCache(id);
if (bitmap == null) {
Log.d(MainActivity.LOG_TAG, "reading bitmap from storage.");
Map.Entry<String, Bitmap> bitmapEntry
= BitmapManager.getBitmapFromStorage(internalStorageDir, id);
if (bitmapEntry != null) {
markerOptions.icon(BitmapDescriptorFactory.fromBitmap(bitmapEntry.getValue()));
addBitmapToMemCache(id, bitmapEntry.getValue());
}
} else {
Log.d(MainActivity.LOG_TAG, "reading bitmap from cache.");
markerOptions.icon(BitmapDescriptorFactory.fromBitmap(bitmap));
}
}
private void addBitmapToMemCache(String key, Bitmap bitmap) {
if (getBitmapFromMemCache(key) == null) {
lruCache.put(key, bitmap);
}
}
private Bitmap getBitmapFromMemCache(String key) {
return lruCache.get(key);
}
}
Dies ist der Code in meinem Activity
, wo ich die Karte starten Laden (dieser Code jedes Mal Bildschirmausrichtung ändert ausgeführt wird):
ClusterManager<Dot> clusterManager = new ClusterManager<>(this, googleMap);
clusterManager.setOnClusterItemInfoWindowClickListener(
new ClusterManager.OnClusterItemInfoWindowClickListener<Dot>() {
@Override
public void onClusterItemInfoWindowClick(Dot dot) {
int id = dot.getId();
String title = dot.getTitle();
Log.d(LOG_TAG, "clicked marker with id " + id
+ " and title " + title + ".");
Intent infoWindowActivityIntent =
new Intent(MainActivity.this, InfoWindowActivity.class);
infoWindowActivityIntent.putExtra("dotId", id);
infoWindowActivityIntent.putExtra("dotTitle", title);
startActivity(infoWindowActivityIntent);
}
});
googleMap.setOnCameraChangeListener(clusterManager);
googleMap.setOnInfoWindowClickListener(clusterManager);
DotRenderer dotRenderer =
new DotRenderer(getApplicationContext(), googleMap, clusterManager,
lruCache, this.getFilesDir().toString());
clusterManager.setRenderer(dotRenderer);
der Speicher Mit jeder Drehung des Bildschirms nimmt der Wert zu. Je mehr ich die Karte zoome (je mehr Markierungen angezeigt werden), desto mehr Speicher wird dem Heap meiner App hinzugefügt, wenn ich den Bildschirm rotiere, bis die Anwendung abstürzt.
manchmal ist der Fehler nicht wie oben, aber zeigt, dass OOM in dieser Zeile in meiner DefaultClusterRenderer<MyItam>
Extension markerOptions.icon(BitmapDescriptorFactory.fromBitmap(bitmap));
passiert ist.
Wenn ich benutzerdefinierte Marker-Symbol deaktivieren (entfernen Sie alle Bitmap
bezogenen Code) das Speicherproblem verschwindet. Bitte helfen Sie mir zu finden, was diese OOM verursacht.
Haben Sie diese auf Ihrer Hauptaktivität ausprobiert? @Override public void onLowMemory() { super.onLowMemory(); mapView.onLowMemory(); } Ich meine in der Aktivität oder Fragment, die die Kartenansicht hinzugefügt ... –
habe ich was probiert? – Salivan
Kommentar bearbeitet .. überprüfen Sie es ... –