Search code examples
javaandroidandroid-studioandroid-layoutandroid-custom-view

Avoid object allocations during draw/layout operations error in Android


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.


Solution

  • 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);
    }