【问题标题】:Android Google Maps v2 big memory consumptionAndroid 谷歌地图 v2 大内存消耗
【发布时间】:2013-10-30 14:34:32
【问题描述】:

我有一个应用程序在使用OutOfMemoryError 的平板电脑上使用一段时间后崩溃。我的应用程序使用带有Fragments 的主从布局。经过大量调试后,我得出的结论是,大量内存消耗是由详细视图中使用的映射引起的。

我创建了一个尽可能简单的示例,它可能缺少许多重要功能,但演示了问题。

TestMapActivity:

public class TestMapActivity extends FragmentActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.test_map_activity);
}

public void newMap(View view) {
    getSupportFragmentManager().beginTransaction().replace(R.id.mapFrame, new TestMapFragment()).addToBackStack(null).commit();
}
}

Activity的布局文件:

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

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onClick="newMap"
    android:text="new map" />

<FrameLayout
    android:id="@+id/mapFrame"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" />

</LinearLayout>

TestMapFragment:

public class TestMapFragment extends Fragment {

protected MapView mMapView;
protected GoogleMap mMap;

@Override
public void onSaveInstanceState(Bundle outState) {
    mMapView.onSaveInstanceState(outState);
    super.onSaveInstanceState(outState);
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mMapView = new MapView(REdroid.sContext);
    mMapView.onCreate(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    super.onCreateView(inflater, container, savedInstanceState);
    View v = inflater.inflate(R.layout.test_map_fragment, container, false);
    ((FrameLayout) v.findViewById(R.id.mapFrame)).addView(mMapView);

    return v;
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    setUpMapIfNeeded();
}

@Override
public void onResume() {
    super.onResume();
    mMapView.onResume();
}

@Override
public void onPause() {
    mMapView.onPause();
    super.onPause();
}

@Override
public void onDestroy() {
    mMapView.onDestroy();
    super.onDestroy();
}

@Override
public void onLowMemory() {
    super.onLowMemory();
    mMapView.onLowMemory();
};

private final void setUpMapIfNeeded() {
    if (mMap == null) {
        mMap = mMapView.getMap();
        if (mMap != null) {
            setUpMap();
        }
    }
}

protected void setUpMap() {
    try {
        MapsInitializer.initialize(getActivity());
    } catch (GooglePlayServicesNotAvailableException e) {
    }
}

}

片段的布局文件:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/mapFrame"
android:layout_width="match_parent"
android:layout_height="match_parent" >

</FrameLayout>

我正在启动活动并按下按钮以显示地图。当我使用 DDMS 检查内存消耗时,我可以看到每次按“新地图”时,“已分配”内存都会增长约 0.5MB。可以想象,当用户观看许多项目时(这在我的应用中是很正常的行为)并且应用每 10 个项目占用 5MB(实际上在实际应用中每个视图占用 1MB)时,这确实是一个问题。

这正常吗?我能做些什么来阻止应用程序使用这么多内存?我在这里读到 Google 地图有一些内存泄漏,但它们会这么大吗?

编辑

我更正了 TestMapActivity.newMap() 函数。我在堆栈中添加了添加事务,因为如果我不将操作放入 backstack,则不会发生内存“泄漏”。

【问题讨论】:

    标签: android google-maps memory out-of-memory google-maps-android-api-2


    【解决方案1】:

    我在两个片段之间切换时遇到了类似的问题,每个片段都有 MapView。

    将此添加到我的代码中解决了巨大的内存消耗问题:

    @Override
    public void onDestroyView() {
        mMapView.clear()
        mMapView.onDestroy();
        super.onDestroyView();
    }
    

    【讨论】:

      【解决方案2】:

      首先,如果 LogCat 中的 GC 对您来说很烦人(我认为是),那么您可以通过消息过滤器将其删除:^(?!.*(GC_)|(Cache)).*$。

      其次,您应该重复使用 MapFragment,或者至少删除它并重新创建它。

      类似:

          public class TestMapActivity extends FragmentActivity {
      
              GoogleMapFragment map;
      
              @Override
              protected void onCreate(Bundle savedInstanceState) {
                  super.onCreate(savedInstanceState);
                  setContentView(R.layout.test_map_activity);
      
                  if (savedInstanceState != null) {
                      // to handle orientation change
                      map = getSupportFragmentManager().findFragmentByTag("map");
                  }
              }
      
              public void newMap(View view) {
                  if (map == null)
                       map = new TestMapFragment();
      
                  getSupportFragmentManager().beginTransaction()
                          .replace(R.id.mapFrame, map, "map").commit();
              }
          }
      

      编辑:

      在您评论您使用 MapView 后,我在 MapView 上搜索了 API,来自:http://developer.android.com/reference/com/google/android/gms/maps/MapView.html

      onDestroy()
          You must call this method from the parent Activity/Fragment's corresponding method.
      

      你在做这个吗?

      编辑2

      刚刚注意到您在片段的 onCreate 中做了:

      mMapView = new MapView(REdroid.sContext);
      

      如何删除该行,而不是在 setupMapIfNeeded 中:

      private final void setUpMapIfNeeded() {
      if (mMapView == null) {
          mMapView = new MapView(context);
      }
      if (mMap == null) {
          mMap = mMapView.getMap();
          if (mMap != null) {
              setUpMap();
          }
      }
      
      }
      

      另外我想我还会在片段的 onCreate 中做一个 setRetainInstance(true)。

      【讨论】:

      • 如你所见,我没有使用谷歌的MapFragment,而是使用嵌入普通FragmentMapView。实际上,地图只是真实应用程序中大视图中的一小部分。上面的例子是这样构造的,只是为了简单。重用Fragment 并不是那么容易,因为实际情况可能会更复杂,然后只是一个接一个地显示许多细节Fragments
      • 如果您查看TestMapFragment 代码,您会发现我确实调用了所有MapView 生命周期函数。
      • 你肯定你的片段确实调用了它的 onDestroy 函数?
      • 实际上它没有被调用,但你知道我做错了什么吗?我们来这里是为了另一件困扰我的事情 - 我在 Google 的文档中没有找到任何关于我应该如何在 Fragment 中处理 MapView 的内容。
      • 认为当您调用新视图时我会在地图视图上显式调用 onDestroy 以确保您没有另一个在后台运行。尽管如此,仍然保留您当前的代码,以便当片段最终被破坏时,地图视图也会这样做。我不熟悉使用地图视图,所以除了我对它的工作原理的想法之外无法给出任何方向。
      猜你喜欢
      • 1970-01-01
      • 2014-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多