Android的 - 许多的OutOfMemoryError例外只能在具有MapView的单一活动 [英] Android - Many OutOfMemoryError exceptions only on single Activity with MapView

查看:155
本文介绍了Android的 - 许多的OutOfMemoryError例外只能在具有MapView的单一活动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我碰到我的用户相当多的OutOfMemoryError报道和每一个报告是来自同一个活动,其中包括一个图形页面。我想,这是一个孤立的异常,在我的应用程序,仅这一个地方,我想不出是什么问题。任何人都可以给我一些指点,为什么发生这种情况?

我已经删除了一些不必要的code这个问题,因此,如果有人认为这个问题可能是,我将它张贴。

堆栈跟踪

 堆栈跟踪#1

java.lang.OutOfMemoryError:位图大小超过VM预算
在android.graphics.Bitmap.nativeCreate(本机方法)
在android.graphics.Bitmap.createBitmap(Bitmap.java:677)
在com.google.android.maps.ZoomHelper.createSnapshot(ZoomHelper.java:444)
在com.google.android.maps.ZoomHelper.beginZoom(ZoomHelper.java:194)
在com.google.android.maps.MapView $ 2.onScaleBegin(MapView.java:371)
在android.view.ScaleGestureDetector.onTouchEvent(ScaleGestureDetector.java:216)
在com.google.android.maps.MapView.onTouchEvent(MapView.java:646)
在android.view.View.dispatchTouchEvent(View.java:3778)
在android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:920)
在android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:959)
在android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:959)
在android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:959)
在com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1716)
在com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1124)
在android.app.Activity.dispatchTouchEvent(Activity.java:2125)
在com.android.internal.policy.impl.PhoneWindow $ DecorView.dispatchTouchEvent(PhoneWindow.java:1700)
在android.view.ViewRoot.handleMessage(ViewRoot.java:1822)
在android.os.Handler.dispatchMessage(Handler.java:99)
在android.os.Looper.loop(Looper.java:143)
在android.app.ActivityThread.main(ActivityThread.java:5068)
在java.lang.reflect.Method.invokeNative(本机方法)
在java.lang.reflect.Method.invoke(Method.java:521)
在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:858)
在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
在dalvik.system.NativeStart.main(本机方法)


堆栈跟踪#2

java.lang.OutOfMemoryError:位图大小超过VM预算
在android.graphics.Bitmap.nativeCreate(本机方法)
在android.graphics.Bitmap.createBitmap(Bitmap.java:468)
在com.google.android.maps.ZoomHelper.createSnapshot(ZoomHelper.java:444)
在com.google.android.maps.ZoomHelper.doZoom(ZoomHelper.java:151)
在com.google.android.maps.ZoomHelper.doZoom(ZoomHelper.java:140)
在com.google.android.maps.MapView.doZoom(MapView.java:1478)
在com.google.android.maps.MapView.doZoom(MapView.java:1487)
在com.google.android.maps.MapController.zoomOut(MapController.java:439)
在com.hookedroid.fishingcompanion.GoogleMaps $ 3.onClick(GoogleMaps.java:133)
在android.view.View.performClick(View.java:2405)
在android.view.View $ PerformClick.run(View.java:8813)
在android.os.Handler.handleCallback(Handler.java:587)
在android.os.Handler.dispatchMessage(Handler.java:92)
在android.os.Looper.loop(Looper.java:123)
在android.app.ActivityThread.main(ActivityThread.java:4627)
在java.lang.reflect.Method.invokeNative(本机方法)
在java.lang.reflect.Method.invoke(Method.java:521)
在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:868)
在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
在dalvik.system.NativeStart.main(本机方法)


堆栈跟踪#3

java.lang.OutOfMemoryError:位图大小超过VM预算
在android.graphics.Bitmap.nativeCreate(本机方法)
在android.graphics.Bitmap.createBitmap(Bitmap.java:468)
在android.graphics.Bitmap.createBitmap(Bitmap.java:435)
在android.graphics.Bitmap.createScaledBitmap(Bitmap.java:340)
在android.graphics.BitmapFactory.finishDe code(BitmapFactory.java:488)
在android.graphics.BitmapFactory.de codeStream(BitmapFactory.java:462)
在android.graphics.BitmapFactory.de codeResourceStream(BitmapFactory.java:323)
在android.graphics.BitmapFactory.de codeResource(BitmapFactory.java:346)
在android.graphics.BitmapFactory.de codeResource(BitmapFactory.java:372)
在com.hookedroid.fishingcompanion.maps.CrosshairOverlay.draw(CrosshairOverlay.java:32)
在com.google.android.maps.OverlayBundle.draw(OverlayBundle.java:45)
在com.google.android.maps.MapView.onDraw(MapView.java:494)
在android.view.View.draw(View.java:6742)
在android.view.ViewGroup.drawChild(ViewGroup.java:1640)
在android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)
在android.view.ViewGroup.drawChild(ViewGroup.java:1638)
在android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)
在android.view.View.draw(View.java:6745)
在android.widget.FrameLayout.draw(FrameLayout.java:352)
在android.view.ViewGroup.drawChild(ViewGroup.java:1640)
在android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)
在android.view.View.draw(View.java:6745)
在android.widget.FrameLayout.draw(FrameLayout.java:352)
在com.android.internal.policy.impl.PhoneWindow $ DecorView.draw(PhoneWindow.java:1913)
在android.view.ViewRoot.draw(ViewRoot.java:1407)
在android.view.ViewRoot.performTraversals(ViewRoot.java:1163)
在android.view.ViewRoot.handleMessage(ViewRoot.java:1727)
在android.os.Handler.dispatchMessage(Handler.java:99)
在android.os.Looper.loop(Looper.java:123)
在android.app.ActivityThread.main(ActivityThread.java:4646)
在java.lang.reflect.Method.invokeNative(本机方法)
在java.lang.reflect.Method.invoke(Method.java:521)
在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:858)
在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
在dalvik.system.NativeStart.main(本机方法)
 

活动

 公共类的GoogleMaps扩展MapActivity {

@覆盖
公共无效的onCreate(包savedInstanceState){
    super.onCreate(savedInstanceState);
    的setContentView(R.layout.googlemaps_layout);

    意图= getIntent();
    CURRENTMODE = intent.getIntExtra(MAP_MODE,0);

    initControls();
    initMembers();

    currentOverlayMode = prefs.getInt(map_viewmode,0);

    populateMap();
}

私人无效initMembers(){
    mDbHelper =新FishingCompanionDB(本);
    mDbHelper.open();
    catchList =新的ArrayList< FishEntry>();

    preFS = preferenceManager.getDefaultShared preferences(本);
    prefsEditor = prefs.edit();
}

私人无效initControls(){
    mMaps =(图形页面)findViewById(R.id.google_maps);
    mMaps.setClickable(真正的);
    mMaps.setLongClickable(真正的);
    mapController = mMaps.getController();

    mOverlayModeBtn =(按钮)findViewById(R.id.googlemaps_overlay_btn);
    mOverlayModeBtn.setOnClickListener(新OnClickListener(){
        公共无效的onClick(视图v){
            如果(currentOverlayMode&小于1)
                currentOverlayMode ++;
            其他
                currentOverlayMode = 0;
            开关(currentOverlayMode){
                案例OVERLAY_STREET:
                    mMaps.setSatellite(假);
                    mMaps.setStreetView(真正的);
                    prefsEditor.putInt(map_viewmode,OVERLAY_STREET);
                    打破;
                案例OVERLAY_SAT:
                    mMaps.setStreetView(假);
                    mMaps.setSatellite(真正的);
                    prefsEditor.putInt(map_viewmode,OVERLAY_SAT);
                    打破;
            }
            prefsEditor.commit();
            mMaps.invalidate();
        }
    });
    mZoomInBtn =(按钮)findViewById(R.id.googlemaps_btn_zoomin);
    mZoomInBtn.setOnClickListener(新OnClickListener(){
        公共无效的onClick(视图v){
            mapController.zoomIn();
        }
    });
    mZoomOutBtn =(按钮)findViewById(R.id.googlemaps_btn_zoomout);
    mZoomOutBtn.setOnClickListener(新OnClickListener(){
        公共无效的onClick(视图v){
            mapController.zoomOut();
        }
    });
}

私人无效populateMap(){
    叠加= mMaps.getOverlays();
    overlays.clear();

    overlays.add(新CrosshairOverlay(这一点,R.drawable.mapcenter));
    mSelectPos =(按钮)findViewById(R.id.googlemaps_select_location);
    mSelectPos.setVisibility(View.VISIBLE);
    mSelectPos.setOnClickListener(新OnClickListener(){
        公共无效的onClick(视图v){
            的GeoPoint centerGp = mMaps.getMapCenter();
            双纬度= centerGp.getLatitudeE6()/ 1E6;
            双LNG = centerGp.getLongitudeE6()/ 1E6;

            我的意图;
            如果(CURRENTMODE == SELECT_POS_WEATHER){
                I =新的意图(GoogleMaps.this,WeatherLookup.class);
                i.putExtra(WEATHER_LAT,LAT);
                i.putExtra(WEATHER_LNG,LNG);
            }
            其他 {
                I =新的意图(GoogleMaps.this,AddLocation.class);
                i.putExtra(LOCATION_LAT,LAT);
                i.putExtra(LOCATION_LNG,LNG);
            }
            i.putExtra(MODE,1);

            startActivity(ⅰ);
            完();
        }
    });

    mMaps.invalidate();
}

@覆盖
保护的布尔isRouteDisplayed(){
    返回false;
}
}
 

十字线重叠

 公共类CrosshairOverlay扩展覆盖{

    私人语境mContext;
    私人诠释RESOURCEID;

    公共CrosshairOverlay(上下文的背景下,INT渣油){
        this.mContext =背景;
        this.resourceId =渣油;
    }

    公共布尔平局(画布油画,图形页面图形页面,布尔影子,时长){
         super.draw(帆布,图形页面,阴影);
         的GeoPoint centerGp = mapView.getMapCenter();
         投影投影= MapView.getProjection()在;
         点中心点= projection.toPixels(centerGp,NULL);
         涂料P =新的油漆();
         BMP位= BitmapFactory.de codeResource(mContext.getResources(),RESOURCEID);

         canvas.drawBitmap(BMP,(centerPoint.x  - (bmp.getWidth()/ 2)),(centerPoint.y  - (bmp.getHeight()/ 2)),p)的;

         返回true;
    }
}
 

DUMPSYS meminfo中

  ** meminfo中的PID 25493 [com.hookedroid.fishingcompanion] **
本机Dalvik的其他总
大小:10036 7495 N / A 17531
分配:9955 3965 N / A 13920
免费电话:80 3530 N / A 3610
(PSS):3717 1480 6703 11900
(共享脏):668 1512 8056 10236
(私法脏):3696 804 5024 9524

对象
浏览次数:0 ViewRoots:0
AppContexts:0活动:0
资产:3 AssetManagers:3
当地粘合剂:19代理粘合剂:21
死亡收件人:1
OpenSSL的套接字:0

SQL
堆:527 MEMORY_USED:527
PAGECACHE_OVERFLOW:62 MALLOC_SIZE:50

DATABASES
pgsz dbsz后备(二)DBNAME
1 16 260 FishingCompanion
1 18 63 google_analytics.db
 

解决方案

我下载的应用程序,并使用它,同时观察通过dumpsys内存。

东西看起来正常,内存被回收每次。我无法重现的情况,但我确实看到一个钉是可能有关。每当你周围的地图或缩放(基本上刷新瓦)的卫星移动,就会出现内存中的一个短暂的高峰。如果你这样做不够快,你不给一个机会,它得到回收,并就上去了。

现在,我的手机是安卓3.3.4,并有pretty的不错的配置,所以也许GC的效率要高得多。虽然我不知道如果我的旧的测试手机将回收内存慢,因此当我到达地图上(比如添加之后才对),我仍然有来自尚未开垦的GC的previous活动内存。然后,我会做什么,我会去我的位置,并检查其中的内容通过放大/缩小。通过从previous活动previous内存组合可能带来的手机到极限。

这仅仅是一个理论,虽然,我在路上,没有获得所有我的测试手机。你知道那是崩溃的手机是什么版本?我会回来的3-4天以后,我可以尝试在我的旧手机的应用程序。

更新: 我已经在这个程序运行更多的实验。我几乎可以肯定,加入了丝丝缕缕将增加更多的回忆。我不停地添加和删除的鱼,并检查该内存一直通过dumpsys meminfo中拔地而起。专业版,甚至是精简版的真实用户谁不断增加和删除的鱼最终可能会打到接近极限,去地图后会触发内存不足的错误,因为有一个记忆跳进入的地图。这里是我的快照添加和删除才对数次

** meminfo中的PID 11572 [com.hookedroid.fishingcompanion.lite] **
                    本机Dalvik的其他总限额位nativeBmp
            大小:18251 19728 N / A 37979 32768 N / A N / A
       分配:17174 14674 N / A 31848 N / A 3144 0
            免费电话:405 3577 N / A 3982 N / A N / AN / A
           (PSS):12750 1771 25944 40465 N / A N / AN / A
  (共享脏):908 1544 5800 8252 N / A N / AN / A
    (私法脏):12732 1008 24208 37948 N / A N / AN / A

您的私有内存跳到共有37948我相信,如果我继续添加和删除鱼,它会抛出OutOfMemoryException异常终

更多更新(几分钟后): 我管理使用上面的理论崩溃的应用程序。我必须有加,并发生之前去除鱼几次。这可能是50多才对以前的应用程序崩溃。

我的猜测是SQL不知何故没有得到妥善清理。看着每一组中添加和删除10鱼类(这是精简版的版本的限制)后的dumpsys,我看

SQL
               堆:6581 MEMORY_USED:6581
 PAGECACHE_OVERFLOW:173 MALLOC_SIZE:50

 DATABASES
      pgsz dbsz后备(二)DBNAME
         1月16日62 FishingCompanion
         1月16日62 FishingCompanion
         1月16日62 FishingCompanion
         1月16日62 FishingCompanion
         1月16日62 FishingCompanion
         1月16日62 FishingCompanion
         1月16日62 FishingCompanion
         1月16日62 FishingCompanion
         1月16日62 FishingCompanion
         1月16日62 FishingCompanion
         1月16日33 FishingCompanion
         1月16日62 FishingCompanion
         1月16日62 FishingCompanion
         1月16日62 FishingCompanion
         1月16日62 FishingCompanion
         1月16日62 FishingCompanion
         1月16日62 FishingCompanion

在SQL存储不断上升,即使我已经删除了才对。如果我继续这样做了一段时间,最终还是会打手机的上限,并会在地图(这会导致在内存中的跳跃)将触发内存溢出异常似乎表明该地图页面,而原因我认为,添加/删除鱼类页面的真正原因部分(我说,因为我不知道我是否增加新的位置会出现类似的效果说的真正原因的一部分)。

我得到了OutMemoryException对的时候,总内存约为58MB(这大概是从电话到电话的不同)。对于一个参考,这里要说的是我得到了一个类似的OutOfMemoryException异常:

D / dalvikvm(11572):GC_FOR_MALLOC释放125K,11%免费25734K / 28743K,外部4047K / 4695K,暂停188ms
D / AndroidRuntime(11572):关闭虚拟机
W / dalvikvm(11572):主题ID = 1:螺纹退出与未捕获的异常(组= 0x4001d648)
E / AndroidRuntime(11572):致命异常:主要
E / AndroidRuntime(11572):java.lang.OutOfMemoryError:位图大小超过VM预算(堆大小= 28743KB,分配= 25734KB,位图大小= 4047KB)
E / AndroidRuntime(11572):在android.graphics.Bitmap.nativeCreate(本机方法)
E / AndroidRuntime(11572):在android.graphics.Bitmap.createBitmap(Bitmap.java:695)
E / AndroidRuntime(11572):在com.google.android.maps.ZoomHelper.createSnapshot(ZoomHelper.java:444)
E / AndroidRuntime(11572):在com.google.android.maps.ZoomHelper.beginZoom(ZoomHelper.java:194)
E / AndroidRuntime(11572):在com.google.android.maps.MapView $ 2.onScaleBegin(MapView.java:380)
E / AndroidRuntime(11572):在android.view.ScaleGestureDetector.onTouchEvent(ScaleGestureDetector.java:216)
E / AndroidRuntime(11572):在com.google.android.maps.MapView.onTouchEvent(MapView.java:682)
E / AndroidRuntime(11572):在android.view.View.dispatchTouchEvent(View.java:3932)
E / AndroidRuntime(11572):在android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:955)
E / AndroidRuntime(11572):在android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1015)
E / AndroidRuntime(11572):在android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1015)
E / AndroidRuntime(11572):在android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1015)

希望它可以帮助

I'm getting quite a few OutOfMemoryError reports from my users and every single report is from the same Activity, which contains a MapView. I'm thinking that it's an isolated exception with just this one place in my app, and I can't figure out what the problem is. Can anybody give me some pointers as to why this is happening?

I've removed some unneeded code for this question, so if somebody thinks the issue could potentially be in that, I'll post it.

Stack Traces

Stack Trace #1

java.lang.OutOfMemoryError: bitmap size exceeds VM budget
at android.graphics.Bitmap.nativeCreate(Native Method)
at android.graphics.Bitmap.createBitmap(Bitmap.java:677)
at com.google.android.maps.ZoomHelper.createSnapshot(ZoomHelper.java:444)
at com.google.android.maps.ZoomHelper.beginZoom(ZoomHelper.java:194)
at com.google.android.maps.MapView$2.onScaleBegin(MapView.java:371)
at android.view.ScaleGestureDetector.onTouchEvent(ScaleGestureDetector.java:216)
at com.google.android.maps.MapView.onTouchEvent(MapView.java:646)
at android.view.View.dispatchTouchEvent(View.java:3778)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:920)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:959)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:959)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:959)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1716)
at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1124)
at android.app.Activity.dispatchTouchEvent(Activity.java:2125)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1700)
at android.view.ViewRoot.handleMessage(ViewRoot.java:1822)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:143)
at android.app.ActivityThread.main(ActivityThread.java:5068)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
at dalvik.system.NativeStart.main(Native Method)


Stack Trace #2

java.lang.OutOfMemoryError: bitmap size exceeds VM budget
at android.graphics.Bitmap.nativeCreate(Native Method)
at android.graphics.Bitmap.createBitmap(Bitmap.java:468)
at com.google.android.maps.ZoomHelper.createSnapshot(ZoomHelper.java:444)
at com.google.android.maps.ZoomHelper.doZoom(ZoomHelper.java:151)
at com.google.android.maps.ZoomHelper.doZoom(ZoomHelper.java:140)
at com.google.android.maps.MapView.doZoom(MapView.java:1478)
at com.google.android.maps.MapView.doZoom(MapView.java:1487)
at com.google.android.maps.MapController.zoomOut(MapController.java:439)
at com.hookedroid.fishingcompanion.GoogleMaps$3.onClick(GoogleMaps.java:133)
at android.view.View.performClick(View.java:2405)
at android.view.View$PerformClick.run(View.java:8813)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4627)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
at dalvik.system.NativeStart.main(Native Method)


Stack Trace #3

java.lang.OutOfMemoryError: bitmap size exceeds VM budget
at android.graphics.Bitmap.nativeCreate(Native Method)
at android.graphics.Bitmap.createBitmap(Bitmap.java:468)
at android.graphics.Bitmap.createBitmap(Bitmap.java:435)
at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:340)
at android.graphics.BitmapFactory.finishDecode(BitmapFactory.java:488)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:462)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:323)
at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:346)
at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:372)
at com.hookedroid.fishingcompanion.maps.CrosshairOverlay.draw(CrosshairOverlay.java:32)
at com.google.android.maps.OverlayBundle.draw(OverlayBundle.java:45)
at com.google.android.maps.MapView.onDraw(MapView.java:494)
at android.view.View.draw(View.java:6742)
at android.view.ViewGroup.drawChild(ViewGroup.java:1640)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)
at android.view.ViewGroup.drawChild(ViewGroup.java:1638)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)
at android.view.View.draw(View.java:6745)
at android.widget.FrameLayout.draw(FrameLayout.java:352)
at android.view.ViewGroup.drawChild(ViewGroup.java:1640)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)
at android.view.View.draw(View.java:6745)
at android.widget.FrameLayout.draw(FrameLayout.java:352)
at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1913)
at android.view.ViewRoot.draw(ViewRoot.java:1407)
at android.view.ViewRoot.performTraversals(ViewRoot.java:1163)
at android.view.ViewRoot.handleMessage(ViewRoot.java:1727)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4646)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
at dalvik.system.NativeStart.main(Native Method)

Activity

public class GoogleMaps extends MapActivity {

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

    intent = getIntent();
    currentMode = intent.getIntExtra("MAP_MODE", 0);

    initControls();
    initMembers();

    currentOverlayMode = prefs.getInt("map_viewmode", 0);

    populateMap();
}

private void initMembers() {
    mDbHelper = new FishingCompanionDB(this);
    mDbHelper.open();
    catchList = new ArrayList<FishEntry>();

    prefs = PreferenceManager.getDefaultSharedPreferences(this);
    prefsEditor = prefs.edit();
}

private void initControls() {
    mMaps = (MapView)findViewById(R.id.google_maps);
    mMaps.setClickable(true);
    mMaps.setLongClickable(true);
    mapController = mMaps.getController();

    mOverlayModeBtn = (Button)findViewById(R.id.googlemaps_overlay_btn);
    mOverlayModeBtn.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            if (currentOverlayMode < 1)
                currentOverlayMode++;
            else
                currentOverlayMode = 0;
            switch (currentOverlayMode) {
                case OVERLAY_STREET:
                    mMaps.setSatellite(false);
                    mMaps.setStreetView(true);
                    prefsEditor.putInt("map_viewmode", OVERLAY_STREET);
                    break;
                case OVERLAY_SAT:
                    mMaps.setStreetView(false);
                    mMaps.setSatellite(true);
                    prefsEditor.putInt("map_viewmode", OVERLAY_SAT);
                    break;
            }
            prefsEditor.commit();
            mMaps.invalidate();
        }
    });
    mZoomInBtn = (Button)findViewById(R.id.googlemaps_btn_zoomin);
    mZoomInBtn.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            mapController.zoomIn();
        }
    });
    mZoomOutBtn = (Button)findViewById(R.id.googlemaps_btn_zoomout);
    mZoomOutBtn.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            mapController.zoomOut();
        }
    });
}

private void populateMap() {
    overlays = mMaps.getOverlays();
    overlays.clear();

    overlays.add(new CrosshairOverlay(this, R.drawable.mapcenter));
    mSelectPos = (Button)findViewById(R.id.googlemaps_select_location);
    mSelectPos.setVisibility(View.VISIBLE);
    mSelectPos.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            GeoPoint centerGp = mMaps.getMapCenter();
            double lat = centerGp.getLatitudeE6()/1E6;
            double lng = centerGp.getLongitudeE6()/1E6;

            Intent i;
            if (currentMode == SELECT_POS_WEATHER) {
                i = new Intent(GoogleMaps.this, WeatherLookup.class);
                i.putExtra("WEATHER_LAT", lat);
                i.putExtra("WEATHER_LNG", lng);
            }
            else {
                i = new Intent(GoogleMaps.this, AddLocation.class);
                i.putExtra("LOCATION_LAT", lat);
                i.putExtra("LOCATION_LNG", lng);
            }
            i.putExtra("MODE", 1);

            startActivity(i);
            finish();
        }
    });

    mMaps.invalidate();
}

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

Crosshair Overlay

public class CrosshairOverlay extends Overlay {

    private Context mContext;
    private int resourceId;

    public CrosshairOverlay(Context context, int resId) {
        this.mContext = context;
        this.resourceId = resId;
    }

    public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when) {
         super.draw(canvas, mapView, shadow);
         GeoPoint centerGp = mapView.getMapCenter();
         Projection projection = mapView.getProjection();
         Point centerPoint = projection.toPixels(centerGp, null);
         Paint p = new Paint();
         Bitmap bmp = BitmapFactory.decodeResource(mContext.getResources(), resourceId);

         canvas.drawBitmap(bmp, (centerPoint.x - (bmp.getWidth()/2)), (centerPoint.y - (bmp.getHeight()/2)), p);

         return true;
    }
}

DUMPSYS MEMINFO

** MEMINFO in pid 25493 [com.hookedroid.fishingcompanion] **
native   dalvik    other    total
size:    10036     7495      N/A    17531
allocated:     9955     3965      N/A    13920
free:       80     3530      N/A     3610
(Pss):     3717     1480     6703    11900
(shared dirty):      668     1512     8056    10236
(priv dirty):     3696      804     5024     9524

Objects
Views:        0        ViewRoots:        0
AppContexts:        0       Activities:        0
Assets:        3    AssetManagers:        3
Local Binders:       19    Proxy Binders:       21
Death Recipients:        1
OpenSSL Sockets:        0

SQL
heap:      527         MEMORY_USED:      527
PAGECACHE_OVERFLOW:       62         MALLOC_SIZE:       50

DATABASES
pgsz     dbsz   Lookaside(b)  Dbname
1       16            260  FishingCompanion
1       18             63  google_analytics.db

解决方案

I downloaded the app and play with it while observing the memory via dumpsys.

Things look normal, memory gets reclaimed every time. I can't reproduce the situation, but I do see one spike that is probably related. Whenever you move around in map or zoom (basically refreshing the tiles) in satellite, there will be a brief spike in memory. If you do it fast enough, you don't give a chance for it to get reclaimed and it will go up.

Now, my phone is Android 3.3.4 and have pretty good configuration, so maybe the GC is much more efficient. I wonder though if my older test phones would reclaim the memory slower and thus when I get to the map (say after adding the fishes), I would still have memory from the previous activity that hasn't been reclaimed by GC. Then what I would do, I would go to my location and check things out by zooming in/out. That combined by previous memory from the previous activities might bring the phones to its limit.

This is just a theory though, I am on the road and don't have access to all my test phones. Do you know what version of the phones that are crashing? I'll be back 3-4 days later and I could try the app on my older phones.

UPDATED: I've run more experiments on this app. I'm almost sure that adding the fishes continuously will add more memories. I kept adding and deleting the fishes and checked that the memory keeps going up via dumpsys meminfo. A real users of the Pro Edition or even the lite who keep adding and removing the fishes might eventually hit close to the limit and going to the map afterward will trigger the out memory error since there is a memory jump going into the map. Here is the snapshot after I added and removed the fishes several times

** MEMINFO in pid 11572 [com.hookedroid.fishingcompanion.lite] **
                    native   dalvik    other    total    limit   bitmap nativeBmp
            size:    19728    18251      N/A    37979    32768      N/A      N/A
       allocated:    17174    14674      N/A    31848      N/A     3144        0
            free:      405     3577      N/A     3982      N/A      N/A      N/A
           (Pss):    12750     1771    25944    40465      N/A      N/A      N/A
  (shared dirty):      908     1544     5800     8252      N/A      N/A      N/A
    (priv dirty):    12732     1008    24208    37948      N/A      N/A      N/A

Your private memory jump to total of 37,948 which I am sure if I continue adding and removing fishes, it will throw the OutOfMemoryException eventually

MORE UPDATE (few minutes later): I manage to crash the app using the theory above. I must have added and removed fishes several times before it occurs. It could be more than 50 fishes before the app crashed.

My guess is the SQL somehow didn't get cleaned properly. Looking at the dumpsys after each set of adding and removing 10 fishes (which is the limit of the lite version), I see that

SQL
               heap:     6581         MEMORY_USED:     6581
 PAGECACHE_OVERFLOW:      173         MALLOC_SIZE:       50

 DATABASES
      pgsz     dbsz   Lookaside(b)  Dbname
         1       16             62  FishingCompanion
         1       16             62  FishingCompanion
         1       16             62  FishingCompanion
         1       16             62  FishingCompanion
         1       16             62  FishingCompanion
         1       16             62  FishingCompanion
         1       16             62  FishingCompanion
         1       16             62  FishingCompanion
         1       16             62  FishingCompanion
         1       16             62  FishingCompanion
         1       16             33  FishingCompanion
         1       16             62  FishingCompanion
         1       16             62  FishingCompanion
         1       16             62  FishingCompanion
         1       16             62  FishingCompanion
         1       16             62  FishingCompanion
         1       16             62  FishingCompanion

The SQL memory keeps going up even though I deleted the fishes already. If I keep doing this for some time, eventually it will hit the upper limit of the phone and going to the map (which cause the jump in the memory) will trigger the out of memory exception seemingly indicating that the map page is the cause whereas I think that the add/remove fish page is part of the real cause (I say "part of the real cause" as I don't know if similar effect would occur say if I add new location).

I got the OutMemoryException right about when the total memory is about 58MB (this is probably different from phone to phone). For a reference, here is a similar OutOfMemoryException that I got:

D/dalvikvm(11572): GC_FOR_MALLOC freed 125K, 11% free 25734K/28743K, external 4047K/4695K, paused 188ms
D/AndroidRuntime(11572): Shutting down VM
W/dalvikvm(11572): threadid=1: thread exiting with uncaught exception (group=0x4001d648)
E/AndroidRuntime(11572): FATAL EXCEPTION: main
E/AndroidRuntime(11572): java.lang.OutOfMemoryError: bitmap size exceeds VM budget(Heap Size=28743KB, Allocated=25734KB, Bitmap Size=4047KB)
E/AndroidRuntime(11572):    at android.graphics.Bitmap.nativeCreate(Native Method)
E/AndroidRuntime(11572):    at android.graphics.Bitmap.createBitmap(Bitmap.java:695)
E/AndroidRuntime(11572):    at com.google.android.maps.ZoomHelper.createSnapshot(ZoomHelper.java:444)
E/AndroidRuntime(11572):    at com.google.android.maps.ZoomHelper.beginZoom(ZoomHelper.java:194)
E/AndroidRuntime(11572):    at com.google.android.maps.MapView$2.onScaleBegin(MapView.java:380)
E/AndroidRuntime(11572):    at android.view.ScaleGestureDetector.onTouchEvent(ScaleGestureDetector.java:216)
E/AndroidRuntime(11572):    at com.google.android.maps.MapView.onTouchEvent(MapView.java:682)
E/AndroidRuntime(11572):    at android.view.View.dispatchTouchEvent(View.java:3932)
E/AndroidRuntime(11572):    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:955)
E/AndroidRuntime(11572):    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1015)
E/AndroidRuntime(11572):    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1015)
E/AndroidRuntime(11572):    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1015)

Hope it helps

这篇关于Android的 - 许多的OutOfMemoryError例外只能在具有MapView的单一活动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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