android MapView always causes an OutOfMemoryError

2019-01-11 20:45发布

I am trying to create a MapView (currently without any overlays) inside some nested elements. It is basically something like ScrollView -> RelativeLayout -> RelativeLayout -> MapView

 <com.google.android.maps.MapView
android:id="@+id/mapview"
android:layout_width="420px"
android:layout_height="300px"
android:clickable="false"
android:apiKey="key"/>

Seems fine for me. There is nothing more that I do with it on startup but it always causes the following:

04-04 13:38:33.910: WARN/dalvikvm(13628): threadid=1: thread exiting with uncaught exception (group=0x40015560)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628): FATAL EXCEPTION: main
04-04 13:38:33.996: ERROR/AndroidRuntime(13628): java.lang.OutOfMemoryError
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at android_maps_conflict_avoidance.com.google.googlenav.map.Map.resize(Map.java:1368)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at android_maps_conflict_avoidance.com.google.googlenav.map.Map.resize(Map.java:1337)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at com.google.android.maps.MapView.onMeasure(MapView.java:590)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at android.view.View.measure(View.java:8313)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:581)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:365)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at android.view.View.measure(View.java:8313)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:581)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:365)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at android.view.View.measure(View.java:8313)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at android.widget.ScrollView.measureChildWithMargins(ScrollView.java:1072)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at android.widget.FrameLayout.onMeasure(FrameLayout.java:250)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at android.widget.ScrollView.onMeasure(ScrollView.java:296)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at android.view.View.measure(View.java:8313)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3138)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at android.widget.FrameLayout.onMeasure(FrameLayout.java:250)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at android.view.View.measure(View.java:8313)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at android.widget.LinearLayout.measureVertical(LinearLayout.java:531)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at android.widget.LinearLayout.onMeasure(LinearLayout.java:309)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at android.view.View.measure(View.java:8313)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3138)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at android.widget.FrameLayout.onMeasure(FrameLayout.java:250)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at android.view.View.measure(View.java:8313)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at android.view.ViewRoot.performTraversals(ViewRoot.java:839)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1859)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at android.os.Handler.dispatchMessage(Handler.java:99)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at android.os.Looper.loop(Looper.java:123)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at android.app.ActivityThread.main(ActivityThread.java:3647)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at java.lang.reflect.Method.invokeNative(Native Method)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at java.lang.reflect.Method.invoke(Method.java:507)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
04-04 13:38:33.996: ERROR/AndroidRuntime(13628):     at dalvik.system.NativeStart.main(Native Method)
04-04 13:38:34.027: WARN/ActivityManager(6000):   Force finishing activity package/.home
04-04 13:38:34.527: WARN/ActivityManager(6000): Activity pause timeout for HistoryRecord{405336d0 package/.home}

Do you have any idea why this is and what I can do to get rid of it? I can't take it out of that view as it is the place where I need it.

Thank you!

7条回答
Evening l夕情丶
2楼-- · 2019-01-11 20:54

I had this problem as well, it occurs when you try to specify the exact dimensions of a mapview. Set one of the dimensions to fill_parent or wrap_content and let the other be whatever dimension you want. That should do the trick.

查看更多
Evening l夕情丶
3楼-- · 2019-01-11 20:56

steemcb is correct, but unfortunately there is also a bug in MapView that causes this to happen even if your layout is good. I got the exact same stack trace as yours. It is a fragile component and small changes in layout type will cause it to break unexpectedly, especially if it's wrapped in a ScrollLayout.

It hasn't yet been addressed by anyone from the Android project.

查看更多
Emotional °昔
4楼-- · 2019-01-11 20:58

I found out something quite simple.

Just place the MapView inside a FrameLayout. Let the FramgeLayout be wrap_content | wrap_content and everything is fine :)

This one fails:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <ScrollView android:layout_width="fill_parent" android:layout_height="fill_parent">

        <RelativeLayout android:layout_width="fill_parent" android:layout_height="wrap_content">

            <view android:layout_width="100dip" android:layout_height="90dip" class="com.google.android.maps.MapView"
                android:apiKey="@string/API_KEY" android:clickable="true" />

        </RelativeLayout>
    </ScrollView>
</RelativeLayout>

I get the following stacktrace:

java.lang.OutOfMemoryError
at com.google.googlenav.map.Map.resize(Unknown Source)
at com.google.android.maps.MapView.onMeasure(MapView.java:554)
at android.view.View.measure(View.java:8172)
at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:578)
at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:362)
at android.view.View.measure(View.java:8172)
at android.widget.ScrollView.measureChildWithMargins(ScrollView.java:989)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:245)
at android.widget.ScrollView.onMeasure(ScrollView.java:286)
at android.view.View.measure(View.java:8172)
at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:578)
at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:362)
at android.view.View.measure(View.java:8172)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3140)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:245)
at android.view.View.measure(View.java:8172)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3140)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:245)
at android.view.View.measure(View.java:8172)
at android.view.ViewRoot.performTraversals(ViewRoot.java:805)
at android.view.ViewRoot.handleMessage(ViewRoot.java:1744)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:144)
at android.app.ActivityThread.main(ActivityThread.java:4937)
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)

An here the solution:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <ScrollView android:layout_width="fill_parent" android:layout_height="fill_parent">

        <RelativeLayout android:layout_width="fill_parent" android:layout_height="wrap_content">

            <FrameLayout android:layout_width="wrap_content" android:layout_height="wrap_content">

                <view android:layout_width="100dip" android:layout_height="90dip" class="com.google.android.maps.MapView"
                    android:apiKey="@string/API_KEY" android:clickable="true" />

            </FrameLayout>

        </RelativeLayout>
    </ScrollView>
</RelativeLayout>

Greetings, Marco

查看更多
Summer. ? 凉城
5楼-- · 2019-01-11 20:58

Actually its caused by placing the MapView in a Scrollview. See android MapView always causes an OutOfMemoryError in nested elements for more information.

查看更多
6楼-- · 2019-01-11 21:06

I don't really see where you are getting an OutOfMemoryError? I do see this:

Caused by: java.lang.IllegalArgumentException: MapViews can only be created inside instances of MapActivity.

Which says you can only create a MapView inside a class that extends MapActivity, and it implies that you do not do this?

查看更多
男人必须洒脱
7楼-- · 2019-01-11 21:07

Actually it is caused by Scrollview creating a buffer to contain the view at each possible position of the scrollbar to enable fast and smooth scrolling. Since a MapView is pretty large when the tiles are loaded during the measure phase then the resulting buffer created by ScrollView can be huge (around 128 M). Unless you set your emulator to have more than 256 M of ram and heap space, it will fail with an out of memory error. You could set your emulator to have 512M of ram and heap space but your app would crash on any device that has less than 512M of ram or insufficient heap space. The best thing to do is to remove the MapView from the ScrollView.

查看更多
登录 后发表回答