谷歌地图Android API v2 SupportMapFragment内存泄漏

时间:2013-01-25 14:36:33

标签: android google-maps-android-api-2 android-maps-v2 supportmapfragment

使用2个简单的活动。第一个Activity只包含一个按钮来启动第二个包含地图的Activity:

主要活动:

public class MainActivity extends Activity {

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

public void goToMap(View view){ //This is just the onClick method for the button
    Intent intent=new Intent( this, BigMapTest.class);
    startActivity(intent);
}

地图活动:

public class BigMapTest extends FragmentActivity {
SupportMapFragment mapFragment;
GoogleMap map;

@Override
protected void onCreate(Bundle arg0) {
    // TODO Auto-generated method stub
    super.onCreate(arg0);

    setContentView(R.layout.travel_diary_big_map);

    mapFragment=(SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.big_map);
    map=mapFragment.getMap();

}

地图活动的XML布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<fragment
        android:id="@+id/big_map"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        class="com.google.android.gms.maps.SupportMapFragment"  
        />

现在当我运行这段代码时,按下按钮移动到带有地图的Activity,然后按回去进入第一个活动......然后重复这个过程,我可以看到堆每次都在增加,直到达到它的极限然后开始夹紧。如果你把地图弄得一团糟(比如缩放),我现在可以得到一个OOM异常。

  

01-25 16:10:13.931:D / dalvikvm(21578):GC_FOR_ALLOC释放1898K,7%免费45859K / 49187K,暂停204ms
  01-25 16:10:14.671:I / dalvikvm-heap(21578):将目标GC堆从52.724MB夹到48.000MB
  01-25 16:10:14.671:D / dalvikvm(21578):GC_CONCURRENT释放2534K,6%释放46554K / 49187K,暂停3ms + 14ms
  01-25 16:10:15.372:I / dalvikvm-heap(21578):将目标GC堆从52.979MB夹到48.000MB
  01-25 16:10:15.382:D / dalvikvm(21578):GC_CONCURRENT释放2273K,5%免费46815K / 49187K,暂停3ms + 15ms
  01-25 16:10:15.622:I / dalvikvm-heap(21578):将目标GC堆从52.604MB夹紧到48.000MB
  01-25 16:10:15.622:D / dalvikvm(21578):GC_FOR_ALLOC释放657K,6%释放46431K / 49187K,暂停202ms
  01-25 16:10:16.203:I / dalvikvm-heap(21578):将目标GC堆从52.959MB夹到48.000MB
  01-25 16:10:16.203:D / dalvikvm(21578):GC_FOR_ALLOC释放1469K,5%免费46796K / 49187K,暂停217ms
  01-25 16:10:16.203:I / dalvikvm-heap(21578):强制收集271144字节分配的SoftReferences   01-25 16:10:16.423:I / dalvikvm-heap(21578):将目标GC堆从52.952MB夹到48.000MB
  01-25 16:10:16.423:D / dalvikvm(21578):GC_BEFORE_OOM释放9K,5%释放46786K / 49187K,暂停219ms
  01-25 16:10:16.423:E / dalvikvm-heap(21578):278744字节分配的内存不足。

任何建议/帮助都将不胜感激。

4 个答案:

答案 0 :(得分:8)

我可以从一些基本的MAT调查中了解到,您所看到的是由Maps V2维护的已下载地图数据的缓存。如果平移和缩放很多,缓存似乎会更大。如果您离开地图并稍后返回到新地图,缓存会缩小。 N次启动示例应用程序的地图活动时,我无法获得N个缓存,缓存大小根据用户的用途而消失和流动。

唉,这个缓存是不可配置的,AFAIK,它的大小,清除时间,溢出到磁盘等等。

因此,默认情况下,您所能做的只是留出一堆健康的堆空间,供Maps V2使用,并采取措施保留在这个较小的堆子集中。

如果您想进行试验,可以尝试在clear()上调用GoogleMap,或在onLowMemory()调用SupportMapFragment,以查看是否有任何帮助可以减少此缓存大小。< / p>

答案 1 :(得分:2)

  

Android Developers 5:10 PM - Google+ Page

     

我们正在推出Google Play服务v3.0,它引入了Google+登录和Google Maps Android API改进。

截至2013年2月26日,gmaps-api-issues page上也描述的此问题现已由当前Google API Update修复。

答案 2 :(得分:1)

我有完全相同的问题。每次托管V2映射的活动开始时,内存都会增加。即使活动结束,它也不会被释放。

因此,解决方法是重用该活动。在清单中创建活动singleTask,而不是finish(),使用moveTaskToBack(true);

答案 3 :(得分:0)

在布局中使用此功能

<LinearLayout
        android:id="@+id/map_container2"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:layout_weight="35.22"
        android:orientation="horizontal" >

        <fragment
            android:id="@+id/map1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            class="com.google.android.gms.maps.SupportMapFragment"
            map:cameraTargetLat="40.72"
            map:cameraTargetLng="-74.00"
            map:cameraZoom="8" />
    </LinearLayout>

这段代码:

onCreate{
   setUpMapIfNeeded();
}

private void setUpMapIfNeeded() {
        // TODO Auto-generated method stub
        // Do a null check to confirm that we have not already instantiated the map.
        if (mMap == null) {
            // Try to obtain the map from the SupportMapFragment.
            mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map1))
                    .getMap();
            // Check if we were successful in obtaining the map.
            if (mMap != null) {
                setUpMap();
            }
        }
    }

private void setUpMap() {
        // TODO Auto-generated method stub
         // Hide the zoom controls as the button panel will cover it.
        mUiSettings = mMap.getUiSettings();
 // Enables/disables zoom gestures (i.e., double tap, pinch & stretch).
        mMap.getUiSettings().setZoomGesturesEnabled(false);
// Enables/disables scroll gestures (i.e. panning the map).
        mMap.getUiSettings().setScrollGesturesEnabled(false);
 // Enables/disables the compass (icon in the top left that indicates the orientation of the
        // map).
        mMap.getUiSettings().setCompassEnabled(false);
        // Add lots of markers to the map.
        addMarkersToMap();

        // Pan to see all markers in view.
        // Cannot zoom to bounds until the map has a size.
        final View mapView = getSupportFragmentManager().findFragmentById(R.id.map1).getView();
        if (mapView.getViewTreeObserver().isAlive()) {
            mapView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
                @SuppressLint("NewApi") // We check which build version we are using.
                @Override
                public void onGlobalLayout() {
                    LatLngBounds bounds = new LatLngBounds.Builder()
                            .include(WOODS)
                            .build();
                    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                      mapView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                    } else {
                      mapView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                    }
                    mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 50));
                }
            });
        }
    }

private void addMarkersToMap() {
        // TODO Auto-generated method stub
         // Uses a colored icon.
        mWoods = mMap.addMarker(new MarkerOptions()
                .position(WOODS)
                .title("Woods")
                .snippet("R. Quatá, 1016, Vila Olimpia - (11) 3849-6868")
                .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE)));
    }