【问题标题】:android MapView always causes an OutOfMemoryError in nested elementsandroid MapView 总是在嵌套元素中导致 OutOfMemoryError
【发布时间】:2011-03-28 14:42:27
【问题描述】:

我正在尝试在一些嵌套元素中创建一个 MapView(目前没有任何覆盖)。 基本上类似于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"/>

对我来说似乎很好。我在启动时没有任何其他操作,但它总是会导致以下问题:

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}

你知道为什么会这样吗?我能做些什么来摆脱它?我不能把它从那个视图中移除,因为它是我需要它的地方。

谢谢!

【问题讨论】:

  • 这就是您在日志猫中看到的有关此异常的所有信息吗?整个异常堆栈跟踪似乎有点短。另一件事是,我认为将 MapView 放入 ScrollView 有点奇怪,因为当有人想在地图中滚动时可能会遇到麻烦。
  • 感谢您的回复。我现在粘贴了整个堆栈跟踪。认为这主要是不必要的东西。不幸的是,我必须将 MapView 放入 ScrollView。我希望(当 MapView 显示时)我可以修改它,当用户在视图上执行滚动手势时,它会采用滚动手势,否则 ScrollView 应该滚动。

标签: android android-mapview out-of-memory


【解决方案1】:

我发现了一些很简单的东西。

只需将 MapView 放在 FrameLayout 中。让 FrameLayout 为 wrap_content | wrap_content 一切都很好:)

这个失败了:

<?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>

我得到以下堆栈跟踪:

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)

这里有一个解决方案:

<?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>

您好, 马可

【讨论】:

  • 每当我遇到这个问题时,我都想支持你的回复,找到这篇文章,你会拯救我的一天!但我就是做不到。只有一次,对不起:)
【解决方案2】:

我也遇到过这个问题,当您尝试指定地图视图的确切尺寸时会出现此问题。将其中一个维度设置为 fill_parent 或 wrap_content 并让另一个维度成为您想要的任何维度。这应该可以解决问题。

【讨论】:

  • 谢谢!不幸的是,这对我不起作用。我仍然收到 OutOfMemoryError。剩余的布局大约需要 8 MB,这对于 MapView 来说可能太多了。
  • 可能 - 我不太确定。如果你去掉布局只留下地图视图,它是否适用于你给它的尺寸?
  • 再次感谢您!我的错误必须在其他地方。我用一些昂贵的对象(我需要这些对象,但我删除了它们进行测试)剥离了我的布局,但我仍然收到错误,尽管我的设备上有 32 MiB 的最大堆大小。我不认为我超过了它。也许 MapView 经常嵌套视图存在一些问题:(
  • 最后一个选项:尝试将 mapview 的直接父级的一个维度定义为任何倾角,将另一个维度定义为填充父级。将 mapview 本身的两个维度都设置为 fill_parent
  • 再次感谢!我试过了,但不幸的是它没有任何区别。
【解决方案3】:

我真的不明白你在哪里得到了 OutOfMemoryError?我确实看到了:

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

这说明你只能在扩展 MapActivity 的类中创建 MapView,这意味着你不能这样做?

【讨论】:

  • 抱歉,我忘记将我的活动改回 MapActivity。现在我用 OutOfMemoryError 粘贴了正确的代码。
【解决方案4】:

看看下面的帖子:

Issue 2181:Memory leak in system when using MapView

似乎这是 MapActivity 内部的东西。该线程已经存在两年多了,并且没有报告为已修复...

编辑:尝试了那里描述的解决方案,它让我找到了类似的解决方案:

try {
        Field mConfigField = MapActivity.class.getDeclaredField("mConfig");
        mConfigField.setAccessible(true);

        Object mConfig = mConfigField.get(this);
        if (null != mConfig)
        {
            Field mConfigContextField = mConfig.getClass().getDeclaredField("context");
            mConfigContextField.setAccessible(true);

            mConfigContextField.set(mConfig, null);

            mConfigField.set(this, null);
        }

    } catch (Exception ex) {
        // Do error handling
    }

【讨论】:

  • 泄漏是一个合法的问题,但在这种情况下它是一个瞬时 OOM - 不同的错误。
【解决方案5】:

steemcb 是正确的,但不幸的是 MapView 中的 there is also a bug 会导致这种情况发生即使你的布局很好。我得到的堆栈跟踪与你的完全相同。它是一个脆弱的组件,布局类型的微小变化会导致它意外中断,尤其是如果它被包裹在 ScrollLayout 中。

Android 项目中的任何人尚未解决此问题。

【讨论】:

    【解决方案6】:

    实际上它是由将 MapView 放置在 Scrollview 中引起的。请参阅android MapView always causes an OutOfMemoryError in nested elements 了解更多信息。

    【讨论】:

      【解决方案7】:

      实际上这是由 Scrollview 创建一个缓冲区来包含滚动条的每个可能位置的视图,以实现快速流畅的滚动。由于在测量阶段加载瓦片时 MapView 非常大,因此 ScrollView 创建的结果缓冲区可能很大(大约 128 M)。除非您将模拟器设置为具有超过 256 M 的 ram 和堆空间,否则它将因内存不足错误而失败。您可以将模拟器设置为具有 512M 的 ram 和堆空间,但您的应用程序会在任何具有少于 512M 的 ram 或堆空间不足的设备上崩溃。最好的办法是从 ScrollView 中删除 MapView。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-01-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多