避免在Android绘制/布局操作期间进行对象分配错误

huangapple go评论76阅读模式
英文:

Avoid object allocations during draw/layout operations error in Android

问题

在Android Studio中,我遇到了以下错误:

> 在绘制/布局操作期间避免对象分配

代码如下:

public class cizim extends View {

    Path path = new Path();
    Paint paint = new Paint();

    public cizim (Context c){
        super(c);
        paint.setColor(Color.BLACK);
        paint.setAntiAlias(true);

    }

    @Override
    protected void onDraw(Canvas canvas){
        canvas.setBitmap(BitmapFactory.decodeResource(getContext().getResources(), R.drawable.foto));
        canvas.drawPath(path, paint);
        super.onDraw(canvas);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event){
        float x = event.getX();
        float y = event.getY();
        path.addCircle(x, y, 10, Path.Direction.CW);
        invalidate();
        return super.onTouchEvent(event);
    }

}

我在以下代码行中遇到了此错误:

canvas.setBitmap(BitmapFactory.decodeResource(getContext().getResources(), R.drawable.foto));

您该如何解决这个问题呢?我需要您的帮助。

英文:

I got this error in Android Studio:

> Avoid object allocations during draw/layout operations

Code:

public class cizim extends View {

    Path path = new Path();
    Paint paint = new Paint();

    public cizim (Context c){
        super(c);
        paint.setColor(Color.BLACK);
        paint.setAntiAlias(true);

    }

    @Override
    protected void onDraw(Canvas canvas){
        canvas.setBitmap(BitmapFactory.decodeResource(getContext().getResources(), R.drawable.foto));
        canvas.drawPath(path, paint);
        super.onDraw(canvas);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event){
        float x = event.getX();
        float y = event.getY();
        path.addCircle(x, y, 10, Path.Direction.CW);
        invalidate();
        return super.onTouchEvent(event);
    }

}

I got the error with this code:

canvas.setBitmap(BitmapFactory.decodeResource(getContext().getResources(), R.drawable.foto));

How can I resolve this problem?

I need your help.

答案1

得分: 1

onDraw方法中绘制视图始终是一个繁重的任务,因为每当视图需要重新绘制时,都会调用onDraw方法,因此想象一下在该方法中分配/创建新对象;这肯定会花费很多时间,并降低应用程序的性能。

因此,不要在每次调用onDraw时都创建位图,而是在视图构造函数中仅创建一次。

在类中添加一个新的实例变量:

public class cizim extends View {

    private Bitmap bitmap;

    ...
}

然后在构造函数中按以下方式创建该对象:

public cizim(Context context) {
    super(context);
    paint.setColor(Color.BLACK);
    paint.setAntiAlias(true);
    bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.foto);
}

最后,将onDraw方法修改为:

@Override
protected void onDraw(Canvas canvas){
    canvas.drawBitmap(bitmap, 0, 0, paint);
    canvas.drawPath(path, paint);
    super.onDraw(canvas);
}

编辑:

实际上,您的代码还存在另一个问题,调用canvas.setBitmap时将导致UnsupportedOperationException。如果参考文档setBitmap会更改画布绘制的位图。由于您需要在屏幕上绘制位图,因此在这里不能使用setBitmap。您实际上需要的是canvas.drawBitmap

将您的onDraw方法更改为:

@Override
protected void onDraw(Canvas canvas){
    canvas.drawBitmap(bitmap, 0, 0, paint);
    canvas.drawPath(path, paint);
    super.onDraw(canvas);
}
英文:

Drawing a view is always a heavy task because onDraw method is invoked whenever the view needs to be drawn again, so imagine allocating/creating new objects in that method; it will certainly take a lot of time and will decrease your app performance.

So instead of creating your bitmap every time onDraw is called, create it only once in your view constructor.

Add a new instance variable to your class:

public class cizim extends View {

    private Bitmap bitmap;

    ...
}

Then in your constructor, create that object as follows:

public cizim(Context context) {
    super(context);
    paint.setColor(Color.BLACK);
    paint.setAntiAlias(true);
    bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.foto);
}

Finally modify your onDraw method to:

@Override
protected void onDraw(Canvas canvas){
    canvas.setBitmap(bitmap);
    canvas.drawPath(path, paint);
    super.onDraw(canvas);
}

Edit:

There is actually another issue with your code that will result in UnsupportedOperationException when calling canvas.setBitmap. If you refer to the documentation, setBitmap will change the bitmap the canvas will draw to. Since you need to draw the bitmap on the screen, you cannot use setBitmap here. So what you actually need is canvas.drawBitmap

Change your onDraw method to:

@Override
protected void onDraw(Canvas canvas){
    canvas.drawBitmap(bitmap, 0, 0, paint);
    canvas.drawPath(path, paint);
    super.onDraw(canvas);
}

huangapple
  • 本文由 发表于 2020年5月29日 20:50:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/62086448.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定