我正在制作一个有两个元素的自定义视图:一个由位图(如地图)和小资源图像(如pin)组成的背景,用于指示地图上的位置。在每个gps位置上更改我的视图get的更新,然后pin移动到新位置。
首先它工作正常,过了一会儿我发现这个错误:
错误/AndroidRuntime(416):
java.lang.OutOfMemory错误:位图
大小超出虚拟机预算
我想这和一直重新画地图有关。也许你有什么办法帮我?
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();
}
}
@我试过这样的方法:
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经常被调用。图像地图为400x400像素
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)
@彼得·克内戈,我在你的回答中编辑过。它在寻找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提到的,有没有一种方法可以让我只在创建时绘制地图图像,然后只在raw上更新pin位置?这似乎是更方便的方式,因为重新绘制地图只使用资源,而且一直都是一样的。
谢谢大家的帮助。这是唯一阻止我完成项目的事情。