我在这里使用MyView
进行绘画。有时当我打开活动时,我得到一个OutOfMemory异常位图大小超过MyView onSizeChanged()
中的VM预算。请问有人对我有什么建议吗?
这是我的代码:
private Paint mPaint;
private Bitmap mBitmap;
private Canvas canvas;
public class MyView extends View
{
private Path mPath;
private Paint mBitmapPaint;
public MyView(Context context) {
super(context);
// TODO Auto-generated constructor stub
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
canvas = new Canvas(mBitmap);
super.onSizeChanged(w, h, oldw, oldh);
}
public void clear(){
mBitmap = Bitmap.createBitmap(480, 480, Bitmap.Config.ARGB_8888);
mPath = new Path();
invalidate();
}
public void destroy() {
if (mBitmap != null) {
mBitmap.recycle();
}
}
@Override
protected void onDraw(Canvas canvas) {
if(action)
{
invalidate();
}
int swidth=(int)(6*(screenWidth/1024));
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
//mPaint.setColor(0xFFFF0000);
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(swidth);
int swidth1=(int)(3*(screenWidth/1024));
Paint painto = new Paint();
painto.setAntiAlias(true);
painto.setColor(getResources().getColor(R.color.magnata));
painto.setStrokeWidth(swidth1);
painto.setStyle(Paint.Style.FILL);
xstart=(int)(15*(screenWidth/1024));
xend=(int)(1010*(screenWidth/1024));
ystart=(int)(90*(screenHeight/600));
y1end=(int)(550*(screenHeight/600));
canvas.drawLine(xstart, ystart, xend, ystart, painto);
canvas.drawLine(xstart, ystart, xstart, y1end, painto);
canvas.drawLine(xstart, y1end, xend, y1end, painto);
canvas.drawLine(xend, ystart, xend, y1end, painto);
Paint p1=new Paint();
p1.setColor(Color.BLACK);
p1.setAntiAlias(true);
Paint p2=new Paint();
p2.setColor(getResources().getColor(R.color.bcolor));
p2.setAntiAlias(true);
float swidth3=(int)(120*(screenWidth/1024));
float swidth4=(int)(4*(screenWidth/1024));
p1.setTextSize(swidth3);
p2.setTextSize(swidth3);
Paint p3=new Paint();
p3.setColor(Color.BLACK);
p3.setStrokeWidth(swidth4);
p3.setAntiAlias(true);
p3.setStyle(Paint.Style.FILL);
Typeface font = Typeface.createFromAsset(getAssets(), "font/KINDTRG.TTF");
Typeface font2=Typeface.createFromAsset(getAssets(), "font/KINDB.TTF");
p1.setTypeface(font);
p2.setTypeface(font);
int xline1=(int)(15*(screenWidth/1024));
int xline2=(int)(500*(screenWidth/1024));
int yline1=(int)(5*(screenHeight/600));
int yline2=(int)(85*(screenHeight/600));
canvas.drawLine(xline1, yline1, xline2, yline1, p3);
canvas.drawLine(xline1, yline2, xline2, yline2, p3);
float width11=(int)(5*(screenWidth/1024));
float width22=(int)(20*(screenWidth/1024));
Paint paint9=new Paint();
paint9.setStrokeWidth(width11);
paint9.setColor(getResources().getColor(R.color.gray));
paint9.setAntiAlias(true);
DashPathEffect dashPath = new DashPathEffect(new float[]{width22,width22}, (float) 5.5);
paint9.setPathEffect(dashPath);
paint9.setStyle(Paint.Style.STROKE);
float width121=(int)(2*(screenWidth/1024));
Paint paint2=new Paint();
paint2.setStrokeWidth(width121);
paint2.setAntiAlias(true);
paint2.setColor(Color.BLACK);
paint2.setTextSize(15);
paint2.setStyle(Style.STROKE);
float width131=(int)(6*(screenWidth/1024));
float textsize22=(int)(17*(screenWidth/1024));
Paint paint1 = new Paint();
paint1.setStyle(Paint.Style.FILL);
paint1.setStrokeWidth(width131);
paint1.setTypeface(font2);
paint1.setAntiAlias(true);
paint1.setColor(Color.BLACK);
paint1.setTextSize(textsize22);
int xtextl=(int)(65*(screenWidth/1024));
int ytext1=(int)(107*(screenHeight/600));
canvas.drawText("Say the words that start with the short a sound .", xtextl, ytext1, paint1);
int ytext2=(int)(228*(screenHeight/600));
int ytext3=(int)(340*(screenHeight/600));
int ytext4=(int)(359*(screenHeight/600));
canvas.drawText("Circle the pictures that start with the short a sound.", xtextl, ytext2, paint1);
canvas.drawText("Say the name of each picture to help you determine the beginning sound.", xtextl,ytext3,paint1);
canvas.drawText(" Press the tennis ball with the correct answer to spell the word.", xtextl, ytext4,paint1);
Paint p=new Paint();
int xcir1=(int)(65*(screenWidth/1024));
int xcir2=(int)(1010*(screenWidth/1024));
int xcir3=(int)(10*(screenWidth/1024));
float rad=(int)(2*(screenWidth/1024));
int ycir1=(int)(212*(screenHeight/600));
int ycir2=(int)(323*(screenHeight/600));
p.setColor(getResources().getColor(R.color.magnata));
for(int i=xcir1;i<xcir2;i+=xcir3)
{
canvas.drawCircle(i, ycir1, rad, p);
}
for(int i=xcir1;i<xcir2;i+=xcir3)
{
canvas.drawCircle(i, ycir2, rad, p);
}
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.drawPath(mPath, mPaint);
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 2;
private void touch_start(float x, float y) {
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
}
private void touch_move(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
mX = x;
mY = y;
}
}
private void touch_up() {
mPath.lineTo(mX, mY);
// commit the path to our offscreen
canvas.drawPath(mPath, mPaint);
// kill this so we don't double draw
mPath.reset();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
Log.i("me.getRawX()",""+ event.getRawX());
Log.i("me.getRawY()",""+ event.getRawY());
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();
break;
}
return true;
}
}
我在下面这一行的onSizeChanged()
内收到错误:
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
答案 0 :(得分:0)
如果您的位图非常大,或者至少如果您释放应用程序内存几乎耗尽,则新位图不再适合应用程序内存,因为旧的位图仍然存在(直到垃圾收集器被丢弃)并解放了它)
您可以通过(显式)首先释放旧位图的内存来解决您的问题。
使用recycle()方法:
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
if(mBitmap != null) {
// Explicitly free memory of old bitmap
mBitmap.recycle();
}
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
// Rest of code
}
您可能希望在clear()
方法中执行相同操作。