Google Maps Android API v2 SupportMapFragment memory leak - программирование
Подтвердить что ты не робот

Google Maps Android API v2 SupportMapFragment memory leak

Использование двух простых действий. Первая активность, которая содержит только кнопку для запуска 2-й операции, которая содержит карту:

Основная деятельность:

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): Clamp target GC heap от 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, приостановлено 202 мс
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): принудительная сборка SoftReferences для размещения 278744 байта
01-25 16: 10: 16.423: I/dalvikvm-heap (21578): Clamp target GC heap от 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 байта.

Любые предложения/помощь будут оценены.

4b9b3361

Ответ 1

Рядом с тем, что я могу сказать из некоторого основного отслеживания MAT, то, что вы видите, - это кеш, поддерживаемый Maps V2 загруженных данных карты. Кажется, что кеш больше, если вы увеличиваете масштаб и увеличиваете масштаб. Кэш сжимается, если вы покинете карту и позже вернетесь к новой карте. Я не мог получить N кэшей из N раз, запуская активность карты вашего примера приложения, а размер кеша отбрасывался и протекал в зависимости от того, что сделал пользователь.

Увы, этот кеш неустроен, AFAIK, с точки зрения того, насколько он большой, когда он очищается, переполняется ли он на диск и т.д.

Итак, по умолчанию все, что вы можете сделать, это оставить в стороне здоровый кусок вашего пространства кучи для карт V2, чтобы играть с ним, и предпринять шаги, чтобы остаться в этом меньшем подмножестве кучи.

Если вы хотите поэкспериментировать, попробуйте вызвать clear() на GoogleMap или onLowMemory() на SupportMapFragment, чтобы узнать, уменьшает ли какая-либо помощь этот размер кэша.

Ответ 2

У меня точно такая же проблема. Память увеличивается каждый раз, когда начинается работа, на которой размещается карта V2. И он не освобождается даже при завершении операции.

Итак, обходным путем является повторное использование этой активности. Сделайте операцию singleTask в манифесте, а вместо finish() используйте moveTaskToBack(true);

Ответ 4

Используйте это в своем макете:

<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)));
    }