我正在製作具有2個元素的自定義視圖:包含像位圖一樣的位圖和像引腳一樣工作的小型資源圖像的背景,以指示地圖上的位置。在每個GPS位置改變我的觀點得到更新和引腳移動到新的位置。Android自定義視圖位圖大小超過虛擬機預算
首先,它炒菜很好,過了一段時間我得到這個錯誤:
ERROR/AndroidRuntime(416): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
它是與重畫地圖的時候,我猜。也許你有任何想法來幫助我?
public class MyMapView extends View {
private int xPos = 0;
private int yPos = 0;
private Bitmap trackMap;
private Paint backgroundPaint;
private Bitmap resizedBitmap;
private Bitmap position;
private Matrix positionMatrix;
private Paint positionPaint;
private int space=0;
public MyMapView(Context context) {
super(context);
init(context, null);
}
public MyMapView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public MyMapView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs);
}
private void init(final Context context, AttributeSet attrs) {
backgroundPaint = new Paint();
backgroundPaint.setFilterBitmap(true);
position = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.position);
positionMatrix = new Matrix();
positionPaint = new Paint();
positionPaint.setFilterBitmap(true);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec));
}
@Override
protected void onDraw(Canvas canvas) {
int width = getMeasuredWidth();
int height = getMeasuredHeight();
if (trackMap!=null)
{
resizedBitmap = Bitmap.createScaledBitmap(trackMap, height, height, true);
space = (width - resizedBitmap.getWidth())/2;
canvas.drawBitmap(resizedBitmap, space, 0, backgroundPaint);
}
if (xPos != 0 && yPos !=0)
{
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.translate(xPos+space-position.getWidth()/2, yPos-position.getHeight()/2);
canvas.drawBitmap(position, positionMatrix, positionPaint);
canvas.restore();
}
}
public void updatePosition(int xpos, int ypos, Bitmap trackImage)
{
xPos=xpos;
yPos=ypos;
trackMap = trackImage;
invalidate();
}
}
@Fedor:我已經試過這樣的事情:
if (trackMap!=null)
{
if (resizedBitmap != null) {
resizedBitmap.recycle();
}
resizedBitmap = Bitmap.createScaledBitmap(trackMap, height, height, true);
space = (width - resizedBitmap.getWidth())/2;
canvas.drawBitmap(resizedBitmap, space, 0, backgroundPaint);
}
}
但仍然是相同的。每次GPS檢測到位置發生變化時,我都會從活動中調用updatePosition(..),所以onDraw get的調用頻率很高。圖像地圖是400×400像素
11-13 20:29:42.121: ERROR/AndroidRuntime(213): Uncaught handler: thread main exiting due to uncaught exception
11-13 20:29:42.150: ERROR/AndroidRuntime(213): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
11-13 20:29:42.150: ERROR/AndroidRuntime(213): at android.graphics.Bitmap.nativeCreate(Native Method)
11-13 20:29:42.150: ERROR/AndroidRuntime(213): at android.graphics.Bitmap.createBitmap(Bitmap.java:468)
11-13 20:29:42.150: ERROR/AndroidRuntime(213): at android.graphics.Bitmap.createBitmap(Bitmap.java:435)
11-13 20:29:42.150: ERROR/AndroidRuntime(213): at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:340)
11-13 20:29:42.150: ERROR/AndroidRuntime(213): at com.vorienteering.customcontrols.MyMapView.onDraw(MyMapView.java:71)
11-13 20:29:42.150: ERROR/AndroidRuntime(213): at android.view.View.draw(View.java:6274)
11-13 20:29:42.150: ERROR/AndroidRuntime(213): at android.view.ViewGroup.drawChild(ViewGroup.java:1526)
11-13 20:29:42.150: ERROR/AndroidRuntime(213): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1256)
11-13 20:29:42.150: ERROR/AndroidRuntime(213): at android.view.ViewGroup.drawChild(ViewGroup.java:1524)
11-13 20:29:42.150: ERROR/AndroidRuntime(213): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1256)
11-13 20:29:42.150: ERROR/AndroidRuntime(213): at android.view.View.draw(View.java:6277)
11-13 20:29:42.150: ERROR/AndroidRuntime(213): at android.view.ViewGroup.drawChild(ViewGroup.java:1526)
11-13 20:29:42.150: ERROR/AndroidRuntime(213): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1256)
11-13 20:29:42.150: ERROR/AndroidRuntime(213): at android.view.View.draw(View.java:6277)
11-13 20:29:42.150: ERROR/AndroidRuntime(213): at android.view.ViewGroup.drawChild(ViewGroup.java:1526)
11-13 20:29:42.150: ERROR/AndroidRuntime(213): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1256)
11-13 20:29:42.150: ERROR/AndroidRuntime(213): at android.view.ViewGroup.drawChild(ViewGroup.java:1524)
11-13 20:29:42.150: ERROR/AndroidRuntime(213): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1256)
11-13 20:29:42.150: ERROR/AndroidRuntime(213): at android.view.View.draw(View.java:6277)
11-13 20:29:42.150: ERROR/AndroidRuntime(213): at android.widget.FrameLayout.draw(FrameLayout.java:352)
11-13 20:29:42.150: ERROR/AndroidRuntime(213): at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1883)
11-13 20:29:42.150: ERROR/AndroidRuntime(213): at android.view.ViewRoot.draw(ViewRoot.java:1332)
11-13 20:29:42.150: ERROR/AndroidRuntime(213): at android.view.ViewRoot.performTraversals(ViewRoot.java:1097)
11-13 20:29:42.150: ERROR/AndroidRuntime(213): at android.view.ViewRoot.handleMessage(ViewRoot.java:1613)
11-13 20:29:42.150: ERROR/AndroidRuntime(213): at android.os.Handler.dispatchMessage(Handler.java:99)
11-13 20:29:42.150: ERROR/AndroidRuntime(213): at android.os.Looper.loop(Looper.java:123)
11-13 20:29:42.150: ERROR/AndroidRuntime(213): at android.app.ActivityThread.main(ActivityThread.java:4203)
11-13 20:29:42.150: ERROR/AndroidRuntime(213): at java.lang.reflect.Method.invokeNative(Native Method)
11-13 20:29:42.150: ERROR/AndroidRuntime(213): at java.lang.reflect.Method.invoke(Method.java:521)
11-13 20:29:42.150: ERROR/AndroidRuntime(213): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
11-13 20:29:42.150: ERROR/AndroidRuntime(213): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:549)
11-13 20:29:42.150: ERROR/AndroidRuntime(213): at dalvik.system.NativeStart.main(Native Method)
@Peter Knego我編輯如你的答案。它找到positionRef和其他一些人有問題。我更新了這樣的代碼:
@Override
protected void onDraw(Canvas canvas) {
int width = getMeasuredWidth();
int height = getMeasuredHeight();
if (trackMapRef != null) {
Bitmap resizedBitmap = Bitmap.createScaledBitmap(trackMapRef.get(), width, height, true);
space = (width - resizedBitmap.getWidth())/2;
canvas.drawBitmap(resizedBitmap, space, 0, backgroundPaintRef.get());
}
if (xPos != 0 && yPos != 0) {
canvas.save(Canvas.MATRIX_SAVE_FLAG);
positionRef = new WeakReference<Bitmap>(BitmapFactory.decodeResource(getContext().getResources(), R.drawable.position));
positionMatrixRef = new WeakReference<Matrix>(new Matrix());
Paint posPaint = new Paint();
posPaint.setFilterBitmap(true);
positionPaintRef = new WeakReference<Paint>(posPaint);
canvas.translate(xPos + space - positionRef.get().getWidth()/2, yPos - positionRef.get().getHeight()/2);
canvas.drawBitmap(positionRef.get(), positionMatrixRef.get(), positionPaintRef.get());
canvas.restore();
}
}
現在它的工作時間稍長。加倍時間。但仍然給出了內存不足的錯誤。 非常感謝您的幫助。
我在想Fedor提到的,有沒有一種方法可以在創建時繪製地圖圖像,然後只更新onDraw的位置?這似乎是更方便的方式,因爲重繪地圖只使用資源,而且它一直都是一樣的。
謝謝大家的幫助。這是阻止我完成項目的唯一因素。
這就是我的想法,但我不知道如何不總是繪製地圖,因爲通常我只需要在創建視圖時繪製它。使用過程中地圖不會改變。 – Alin 2010-11-14 07:48:17