热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

在内存错误中,谷歌映射apiv2。-googlemapsapiv2outofmemoryerror

ihaveahugememoryprobleminmyapp.iamusinggooglemapapiv2withClusterManagerandcustom

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:

我的应用程序存在很大的内存问题。我正在使用带有ClusterManager和自定义标记的谷歌map api v2。我通过调用markerOptions.icon(BitmapDescriptorFactory.fromBitmap(bitmap))提供图像;每个标记基于其类别。问题是:在多次屏幕旋转后,我的应用程序因为OOM错误而崩溃:

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)

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 object everytime the Activity is recreated and map needs to be redrawn.

我有一个带有位图的LruCache对象,这意味着我不重新创建它们,而是重用它们。我可以清楚地看到,每个位图对象都是从缓存中获取的,而不是从其他地方获取的。但是,如果位图还没有在缓存中(第一次加载),我将从应用程序的内部存储中加载它,但只有在第一次加载位图时才会发生这种情况。我将LruCache实例保存在一个保留的片段实例中,并在每次重新创建活动并重新绘制映射时将其传递给我的自定义DefaultClusterRenderer 对象。

this is my DefaultClusterRenderer extension:

这是我的DefaultClusterRenderer扩展名:

public class DotRenderer extends DefaultClusterRenderer {
private final String internalStorageDir;
private final LruCache lruCache;

public DotRenderer(Context context, GoogleMap googleMap, ClusterManager clusterManager,
                   LruCache 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 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);
}
}

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

这是我在活动中开始加载地图的代码(每次屏幕方向改变时都执行此代码):

    ClusterManager clusterManager = new ClusterManager<>(this, googleMap);
    clusterManager.setOnClusterItemInfoWindowClickListener(
            new ClusterManager.OnClusterItemInfoWindowClickListener() {
                @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.

内存随着屏幕的每一次旋转而不断增加,我在地图上缩放的次数越多(显示的标记越多),当我旋转屏幕直到应用程序崩溃时,添加到应用程序堆中的内存就越多。

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

有时错误与上面不同,但显示OOM发生在我的DefaultClusterRenderer 扩展markerOptions.icon .icon(BitmapDescriptorFactory.fromBitmap(位图))中的这一行;

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.

如果我禁用自定义标记图标(删除所有位图相关代码),内存问题就会消失。请帮助我找出是什么原因导致这个OOM的出现。

2 个解决方案

#1


1  

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.

我遇到了这个问题,试图在演示模式下运行一个应用程序,每次运行几个小时。不管我怎么尝试,30分钟后,我将看到这个崩溃,而没有一个可读的堆栈报告。

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:

我尝试了System gc(),分离片段、单例活动、更新谷歌播放服务到最新版本、清除对覆盖的引用、将映射生命周期附加到活动等等。经过多次失败的尝试和许多挫折,我终于找到了一些有用的东西。它不是地图bug的修复程序,但它阻止了我的应用程序崩溃:

    

#2


0  

Alright... I think this should work...

好吧……我认为这应该行得通……

Add googleMap.clear() whenever you want to reset the map.

在需要重置映射时添加googleMap.clear()。

Hope this will help you.

希望这能对你有所帮助。


推荐阅读
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • 796.[APIO2012]派遣在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿。在这个帮派里,有一名忍者被称之为Master。 ... [详细]
  • 本文介绍了H5游戏性能优化和调试技巧,包括从问题表象出发进行优化、排除外部问题导致的卡顿、帧率设定、减少drawcall的方法、UI优化和图集渲染等八个理念。对于游戏程序员来说,解决游戏性能问题是一个关键的任务,本文提供了一些有用的参考价值。摘要长度为183字。 ... [详细]
  • SQL Server 内存中OLTP内部机制概述(一)
    内存中OLTP(项目名为“Hekaton”)是一个新的完全集成到SQLServer中的数据库引擎组件。它专为访问内存常驻数据的OLTP工作负荷而进行优化。内存中OLTP有助于OLT ... [详细]
  • Apple iPad:过渡设备还是平板电脑?
    I’vebeenagonizingoverwhethertopostaniPadarticle.Applecertainlydon’tneedmorepublicityandthe ... [详细]
  • 尾部|柜台_Java并发线程池篇附场景分析
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了Java并发-线程池篇-附场景分析相关的知识,希望对你有一定的参考价值。作者:汤圆个人博客 ... [详细]
  • 数据结构与算法习题replacementselectionsort(置换选择排序)TimeLimit:1000msMemoryLimit:65536kBDescrip ... [详细]
  • 32位ubuntu编译android studio,32位Ubuntu编译Android 4.0.4问题
    问题一:在32位Ubuntu12.04上编译Android4.0.4源码时,出现了关于emulator的错误,关键是其Makefile里的 ... [详细]
  • 4.3.2Tuple是否可以跨页面PostgreSQLusesafixedpagesize(commonly8kB),anddoesnotallowtuplestospanmult ... [详细]
author-avatar
爱你116564
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有