Frage

Ich habe eine benutzerdefinierte Ansicht habe, in dem ich brauche zwei Bitmaps zu ziehen, ist ein Hintergrund, was das Bild einer Karte und man ist ein Stift, der auf der Oberseite / linke Position in Leinwand gezogen werden.

Die beiden Bilder sind gezeichnet OnDraw und gleich bleiben während des Live von der Tätigkeit, die die Ansicht enthält. Nach einer Weile ich ein

erhalten

OutOfMemoryError: Bitmap-Größe überschreitet VM Budget

Das bedeutet, dass ich ein Leck haben und die Bitmaps nicht bekommen Müll gesammelt. Ich habe diese Frage vor, aber jetzt ist die Situation ein wenig geändert. Ich habe eine init-Methode, wo ich die Bitmaps gesetzt ich verwenden möchte, aber das ist noch kein guter Ansatz, erscheint der Fehler später, aber immer noch da.

Hier ist der Code

public class MyMapView extends View {
private int xPos = 0;
private int yPos = 0;
private int space = 0;

private Bitmap resizedBitmap;
private Bitmap position;
private Bitmap mapBitmap;

public void setMapBitmap(Bitmap value) {
    this.mapBitmap =  value;
}

public MyMapView(Context context) {
 super(context);
}

public MyMapView(Context context, AttributeSet attrs) {
 super(context, attrs);
}

public MyMapView(Context context, AttributeSet attrs, int defStyle) {
 super(context, attrs, defStyle);
}

public void init(final Context context) {
 Paint paint = new Paint();
    paint.setFilterBitmap(true);

    int width = getMeasuredWidth();
    int height = getMeasuredHeight();

    resizedBitmap = Bitmap.createScaledBitmap(mapBitmap, height, height, true);
    position = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.position);
    space = (width - resizedBitmap.getWidth()) / 2;
}

public void destroy()
{
 resizedBitmap.recycle();
 resizedBitmap=null;
 position.recycle();
 position=null;
 mapBitmap.recycle();
 mapBitmap=null;
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec));
}

@Override
protected void onDraw(Canvas canvas) {

     if (mapBitmap != null) {
         canvas.drawBitmap(resizedBitmap, space, 0, null);
     }

     if (xPos != 0 && yPos != 0) {
         canvas.translate(xPos + space - position.getWidth() / 2, yPos - position.getHeight() / 2);
         canvas.drawBitmap(position, new Matrix(), new Paint());

     }
}

 public void updatePosition(int xpos, int ypos)
 {
   xPos = xpos;
      yPos = ypos;
      invalidate();
 }
}

Ich nenne die setMapBitmap () und init () auf onCreate der Aktivität, die die Ansicht enthält. Dort weiß ich, was Bitmap wird als Karte verwendet werden. onPause der Aktivität nenne ich die destroy () der Ansicht. Ich bekomme immer noch Fehler. Ich habe diese Zeilen lesen href="http://mobi-solutions.blogspot.com/2010/08/how-to-if-you-want-to-create-and.html"> aber ich weiß nicht, wie es auf meinem Fall anpassen

Ich bin offen für jede andere Lösung. Bitte beachten Sie, dass ich die Karte Bitmap, um die Größe (bezogen auf der Höhe des Layouts, die es in mai Aktivität enthält) und noch in der Lage sein, die Position auf richtige Stelle zu ziehen.

War es hilfreich?

Lösung

Sie haben offensichtlich ein Speicherleck. Lesen Sie, wie Sie vermeiden Speicherlecks und wie finden Speicherlecks .

Hier ist ein Code zur Verwendung WeakReference Refactoring:

public class MyMapView extends View {
    private int xPos = 0;
    private int yPos = 0;
    private int space = 0;

    private WeakReference<Bitmap> resizedBitmap;
    private WeakReference<Bitmap> position;
    private WeakReference<Bitmap> mapBitmap;

    public void setMapBitmap(Bitmap value) {
        this.mapBitmap = new WeakReference<Bitmap>(value);
    }

    public MyMapView(Context context) {
        super(context);
    }

    public MyMapView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyMapView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public void init(Bitmap mapBitmap) {
        Paint paint = new Paint();
        paint.setFilterBitmap(true);

        int width = getMeasuredWidth();
        int height = getMeasuredHeight();

        resizedBitmap = new WeakReference<Bitmap>(Bitmap.createScaledBitmap(
            mapBitmap, width, height, true));
        position = new WeakReference(BitmapFactory.decodeResource(
            getContext().getResources(), R.drawable.position));
        space = (width - resizedBitmap.get().getWidth()) / 2;
    }

//    public void destroy() {
//        resizedBitmap.recycle();
//        resizedBitmap = null;
//        position.recycle();
//        position = null;
//        mapBitmap.recycle();
//        mapBitmap = null;
//    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),
            MeasureSpec.getSize(heightMeasureSpec));
    }

    @Override
    protected void onDraw(Canvas canvas) {

        if (mapBitmap != null) {
            canvas.drawBitmap(resizedBitmap.get(), space, 0, null);
        }

        if (xPos != 0 && yPos != 0) {
            canvas.translate(xPos + space - position.get().getWidth() / 2, 
                yPos - position.get().getHeight() / 2);
            canvas.drawBitmap(position.get(), new Matrix(), null);

        }
    }

    public void updatePosition(int xpos, int ypos) {
        xPos = xpos;
        yPos = ypos;
        invalidate();
    }
}

Andere Tipps

Etwas, das im Code markiert mich ist, dass Sie nicht alle Ihre Bitmaps scheinbar recyceln. Hier sind ein paar Code-Schnipsel, die helfen könnten:

bmp = getBitmapFromRessourceID(R.drawable.menu);
ratio = (float)this.height/(float)bmp.getScaledHeight(canvas);
temp = Bitmap.createScaledBitmap(bmp, (int)(bmp.getWidth()*ratio), (int) (bmp.getHeight()*ratio-10), false);
bmp.recycle();
bmp = temp;

und

Bitmap temp = BitmapFactory.decodeResource(context.getResources(), resource, opts);
Bitmap bmp = Bitmap.createBitmap(temp, 0, 0, temp.getWidth(), temp.getHeight(), flip, true);
temp.recycle();
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top