谷歌API V2映射内存不足的错误 [英] google maps api v2 out of memory error

查看:234
本文介绍了谷歌API V2映射内存不足的错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的应用程序巨大的内存问题。我使用谷歌地图API V2与 ClusterManager 和自定义标记。我通过提供呼叫的图像 markerOptions.icon(BitmapDesc​​riptorFactory.fromBitmap(位图)); 基于其类别中的每个标记。问题是:几个屏幕旋转,因为OOM错误,我的应用程序崩溃后:

i have a huge memory problem in my app. i am using google map api v2 with ClusterManager and custom markers. i supply an image via call to markerOptions.icon(BitmapDescriptorFactory.fromBitmap(bitmap)); for each marker based on its category. the problem is: after several screen rotations my app crashes because of OOM error:

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)

我有我的位图 LruCache 对象,这意味着我不重新创建它们,而是重用他们。我可以清楚地看到每一个位图对象从缓存中获取,而不是从其他地方。但是,如果位图不在缓存中,但(第一次加载),我从我的应用程序的内部存储加载它,但它只是happnes当位图是laoded第一次。我不断的 LruCache 实例在保留片段实例,并将其传递给我的自定义 DefaultClusterRenderer< MyObject的方式> 对象每次在活动的重建,并需要重新绘制地图

i have a LruCache object with my Bitmaps, it means that i do not recreate them, but reuse them. i can clearly see that every Bitmap object is taken from the cache, not from elsewhere. However, if the Bitmap is not in the cache yet (first time loading) i load it from my app's internal storage, but it only happnes when the Bitmap is laoded the first time. i keep the instance of the LruCache in a retained Fragment instance and pass it to my custom DefaultClusterRenderer<MyObject> object everytime the Activity is recreated and map needs to be redrawn.

这是我的 DefaultClusterRenderer&LT; MyItem&GT; 扩展:

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

这是我的活动里面的code 在那里我开始加载地图(这code执行每次屏幕方向改变):

this is the code inside my Activity where i start loading the map (this code is executed everytime screen orientation changes):

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

内存保持与每一个屏幕旋转增加,我越放大地图(越标记显示)当我旋转屏幕,直到应用程序崩溃的内存量越多被添加到我的应用程序的堆。

the memory keeps increasing with every screen rotation, the more i zoom in the map (the more markers are shown) the more amount of memory is added to my app's heap when i rotate the screen until application crashes.

有时错误是不喜欢上面的,但显示OOM发生在这条线在我的 DefaultClusterRenderer&LT; MyItam&GT; 扩展 markerOptions.icon(BitmapDesc​​riptorFactory .fromBitmap(位图));

sometimes the error is not like above, but shows that OOM happened at this line in my DefaultClusterRenderer<MyItam> extension markerOptions.icon(BitmapDescriptorFactory.fromBitmap(bitmap));.

如果我禁用定制标记图标(删除所有位图相关code)内存问题消失了。请帮我找什么原因导致这种OOM出现​​。

if i disable custom marker icon (remove all the Bitmap related code) the memory problem vanishes. please help me to find what causes this OOM to appear.

推荐答案

我就遇到了这个问题,尝试运行在演示模式的应用程序在一个几个小时的时间。不管是什么我想,30分钟后,我就看到这崩溃而不可读栈报告。

I ran into this problem trying to run an app on demo mode for a few hours at a time. No matter what I tried, after 30 minutes, I would see this crash without a readable stack report.

我试过系统GC(),分离片段,单活动,更新谷歌播放服务,以最新,清除引用覆盖,地图生命周期附加到活动,什么不是。
许多失败的尝试和许多挫折后,我终于找到了一些工作。这不是对地图的bug修复,但它一直在我的应用程序崩溃:

I tried System gc(), detaching the fragment, singleton activities, updating google play services to the latest, clearing references to overlays, attaching map lifecycle to activity and what not. After many failed attempts and a lot of frustration I finally found something that worked. It's not a fix for the map bug, but it kept my app from crashing:

    <application
    ...
    android:largeHeap="true">

这篇关于谷歌API V2映射内存不足的错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆