Размер растрового изображения Android OutOfMemoryError превышает бюджет виртуальной машины - PullRequest
3 голосов
/ 19 июня 2011

У меня есть приложение, в котором я читаю некоторые данные GPS и отображаю их на карте, а также добавляю наложение в той позиции, которая представляет собой небольшое .png изображение.

Я читаю данные в потоке Async Task и методом onProgressUpdate я обновляю свой графический интерфейс, добавляя оверлей в новой позиции. Вот мой код:

     Drawable marker;          
public void onCreate(Bundle savedInstanceState) {
            marker=getResources().getDrawable(R.drawable.curent_loc);
    marker.setBounds(0, 0, marker.getIntrinsicWidth(),
            marker.getIntrinsicHeight());

    }

Здесь я читаю данные GPS:

public class InitTask extends AsyncTask<Void, GeoPoint, Void> {
protected Void doInBackground(Void... voids) {

        p = new GeoPoint(latitude, longitude);
                    publishProgress(p);
                    Thread.sleep(1500);
                }

/*in here I update my GUI*/
  protected void onProgressUpdate(GeoPoint... progress1) {
    mapView.getOverlays().add(new SitesOverlay(marker,progress1[0]));
                theRouteDraw(progress1[0]);
                }
        }

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

Все идет хорошо, пока в какой-то момент я не получу следующее исключение:

java.lang.OutOfMemoryError: bitmap size exceeds VM budget
 at android.graphics.BitmapFactory.nativeDecodeByteArray(Native Method)
at android.graphics.BitmapFactory.decodeByteArray(BitmapFactory.java:392)
at android.graphics.BitmapFactory.decodeByteArray(BitmapFactory.java:405)
at com.google.android.maps.StreetViewRenderer.getOverlay(StreetViewRenderer.java:149)
com.google.android.maps.StreetViewRenderer.renderTile(StreetViewRendere
at    com.google.android.maps.AndroidTileOverlayRenderer.renderTile(AndroidTileOverlayRenderer.java:62)
at com.google.googlenav.map.Map.drawTile(Unknown Source)
at com.google.googlenav.map.Map.drawMapBackground(Unknown Source)
at com.google.googlenav.map.Map.drawMap(Unknown Source)
at com.google.android.maps.MapView.drawMap(MapView.java:1029)
at com.google.android.maps.MapView.onDraw(MapView.java:468)
at android.view.View.draw(View.java:6535)
at android.view.ViewGroup.drawChild(ViewGroup.java:1531)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1258)
at android.view.ViewGroup.drawChild(ViewGroup.java:1529)

Я пытался recycle рисовать, но все равно получаю эту ошибку, и через некоторое время я нашел это:

//decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f){
    try {
        //Decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(new FileInputStream(f),null,o);

        //The new size we want to scale to
        final int REQUIRED_SIZE=70;

        //Find the correct scale value. It should be the power of 2.
        int width_tmp=o.outWidth, height_tmp=o.outHeight;
        int scale=1;
        while(true){
            if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
                break;
            width_tmp/=2;
            height_tmp/=2;
            scale*=2;
        }

        //Decode with inSampleSize
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize=scale;
        return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
    } catch (FileNotFoundException e) {}
    return null;
}

Я нашел это здесь: Странно нехватка памяти при загрузке изображения в растровый объект

Но у меня есть несколько проблем в понимании этого:

* Во-первых, почему в качестве параметра используется File f? Это то, что я хочу использовать? Обязательно ли это делать каждый раз, когда я использую этот чертеж или только в onCreate()?

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

1 Ответ

2 голосов
/ 19 июня 2011

Это была огромная проблема с Android целую вечность. Класс Bitmap, функция getDrawable и т. Д. Опирается на базовый bitmap.h, который доступен как часть NDK. Всякий раз, когда getDrawable возвращает растровое изображение, по какой-то причине Android не освобождает должным образом память, когда она нам больше не нужна.

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

Надеюсь, это поможет.

...