Google API MapView OutOfMemoryError Проблемы - PullRequest
4 голосов
/ 21 февраля 2011

Я использую Google API MapView в своем приложении для Android, и я обнаружил, что он часто встречается с этой ошибкой, когда я прокручиваю и увеличиваю карту.Они имеют тенденцию происходить довольно быстро (20 секунд использования карт), поэтому я считаю, что это будет проблемой.Ниже моя трассировка стека.Я занимаюсь разработкой HTC Desire с объемом памяти 24 МБ.

Какие-либо идеи или настройки, которые я могу сделать, чтобы уменьшить частоту этих ошибок?

java.lang.OutOfMemoryError: bitmap size exceeds VM budget
    at android.graphics.Bitmap.nativeCreate(Native Method)
    at android.graphics.Bitmap.createBitmap(Bitmap.java:574)
    at com.google.android.maps.ZoomHelper.createSnapshot(ZoomHelper.java:444)
    at com.google.android.maps.ZoomHelper.doZoom(ZoomHelper.java:151)
    at com.google.android.maps.ZoomHelper.doZoom(ZoomHelper.java:140)
    at com.google.android.maps.MapView.doZoom(MapView.java:1478)
    at com.google.android.maps.MapView.doZoom(MapView.java:1487)
    at com.google.android.maps.MapView$6.onZoom(MapView.java:1442)
    at android.widget.ZoomButtonsController$3.onClick(ZoomButtonsController.java:268)
    at android.view.View.performClick(View.java:2408)
    at android.view.View$PerformClick.run(View.java:8817)
    at android.os.Handler.handleCallback(Handler.java:587)
    at android.os.Handler.dispatchMessage(Handler.java:92)
    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:868)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
    at dalvik.system.NativeStart.main(Native Method)


debug.heap native: allocated 10.63MB of 11.01MB (385.98KB free)
debug.memory: allocated: 17.95MB of 24.00MB (13.50MB free)

Это мое наложение.У меня есть около 50 элементов, отображающих PNG-изображение 96x96 с некоторой прозрачностью (размер файла 6 КБ).

public class StationItemizedOverlay extends ItemizedOverlay<OverlayItem>
{
    private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
    private ArrayList<Location> locations = new ArrayList<Location>();


    private Context mContext;

    public StationItemizedOverlay(Drawable defaultMarker, Context context)
    {
        super(boundCenterBottom(defaultMarker));
        this.mContext = context;
    }

    /**
     * Add a range of locations to this overlay
     * 
     * @param locations The locations to add
     */
    public void addRange(List<Location> locations)
    {
        for (Location l : locations)
        {
            addOne(l);
        }
        populate();
    }

    /**
     * Add a location to this overlay
     * 
     * @param location The location
     */
    public void add(Location location)
    {
        addOne(location);
        populate();
    }

    /**
     * Remove a location from this overlay
     * @param location The location to remove
     */
    public void remove(Location location)
    {
        int position = locations.indexOf(location);

        if (position >= 0)
        {
            mOverlays.remove(position);
            locations.remove(position);
            populate();
        }
    }

    private void addOne(Location location)
    {
        locations.add(location);
        int lat = location.getMicroLatitude();
        int lon = location.getMicroLongitude();
        GeoPoint point = new GeoPoint(lat, lon);
        OverlayItem item = new OverlayItem(point, location.getRealName(), location.getRealName());
        mOverlays.add(item);
    }

    @Override
    protected boolean onTap(int index)
    {
        OverlayItem item = mOverlays.get(index);
        AlertDialog.Builder dialog = new AlertDialog.Builder(mContext);
        dialog.setTitle(item.getTitle());
        dialog.setMessage(item.getSnippet());
        dialog.show();
        return true;
    }

    @Override
    protected OverlayItem createItem(int i)
    {
        return mOverlays.get(i);
    }

    @Override
    public int size()
    {
        return mOverlays.size();
    }

}

Это мой MapActivityClass

public class StationFinder extends MapActivity
{
    IUIInterface dataInterface = UIInterfaceFactory.getInterface();

    MapView mapView;

    List<Overlay> mapOverlays;
    Drawable drawable;
    StationItemizedOverlay trainItemizedOverlay;

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

        mapView = (MapView) findViewById(R.id.stationFinderUI_mapview);
        mapView.setBuiltInZoomControls(true);

        mapOverlays = mapView.getOverlays();
        drawable = getResources().getDrawable(R.drawable.dash_train_btn_default);
        trainItemizedOverlay = new StationItemizedOverlay(drawable, this);

        myMapController = mapView.getController();
        myMapController.setZoom(8); // zoom level selected from google map .com

        // center this location on northern ireland
        centerLocation(Settings.getNorthernIrelandCenter().getGeoPoint());

        mapOverlays.add(trainItemizedOverlay);

        // add data to the adapters only whenever the data is loaded
        if (!dataInterface.isDataLoaded())
        {
            // data is not loaded
            // so make a listener for the data loaded event
            dataLoadedListener = new IEventListener()
            {
                public void action(Object optionalData)
                {
                    // the event has been triggered
                    // register this function to run in the UI thread of the application
                    runOnUiThread(new Runnable()
                    {
                        public void run()
                        {
                            dataLoaded();
                        }
                    });
                }
            };
            // register the listener for data loaded events
            dataInterface.registerDataLoaded(dataLoadedListener);
            // call the data loaded function now incase the data has since been loaded by 
            // the application between registering for the event
            if (dataInterface.isDataLoaded())
            {
                dataLoaded();
            }
        }
        else
        {
            // data already loaded so run immediately
            dataLoaded();
        }



    }

    IEventListener dataLoadedListener = null;
    boolean isDataLoaded = false;

    private void dataLoaded()
    {
        // make sure this function is only called once
        if (isDataLoaded)
            return;
        isDataLoaded = true;

        // IMPORTANT STUFF GOES HERE



        trainItemizedOverlay.addRange(dataInterface.getAllLocations());


        // clean up the data load listener
        if (dataLoadedListener != null)
        {
            dataInterface.removeDataLoaded(dataLoadedListener);
            dataLoadedListener = null;
        }
    }

    private MapController myMapController;

    private void centerLocation(GeoPoint center)
    {
        myMapController.animateTo(center);

        myMapController.setCenter(center);
    };


    @Override
    protected boolean isRouteDisplayed()
    {
        return false;
    }

Ответы [ 2 ]

1 голос
/ 10 марта 2011

Странно, эта проблема прекратилась.Не знаю, почему в настоящее время, хотя я думаю, что некоторые другие оптимизации памяти, которые я сделал, сделали большие блоки памяти доступными для рисования карты

0 голосов
/ 21 февраля 2011

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

...