I have custom view which draws bitmaps on canvas. I want to improve my code so the memory chart in profiler looks smooth. I want to know why there are such leaps and GC removing objects every few second. It's worth mentioning that if I remove characterCreator.draw(canvas); from draw() method then the chart is smooth. Here is how my chart looks like now:
And now the important code:
CharacterCreatorView.java
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
if(characterCreator != null)
characterCreator.draw(canvas);
invalidate();
}
CharacterCreator.java
private static final int ROW_BOTTOM_TO_TOP = 8;
private static final int ROW_RIGHT_TO_LEFT = 9;
private static final int ROW_TOP_TO_BOTTOM = 10;
private static final int ROW_LEFT_TO_RIGHT = 11;
private static final int COL_COUNT = 13;
private static final int ROW_COUNT = 21;
private final Bitmap[] leftToRights;
private final Bitmap[] rightToLefts;
private final Bitmap[] topToBottoms;
private final Bitmap[] bottomToTops;
public CharacterCreator(Bitmap baseSprite) {
this.image = baseSprite;
this.widthAllCols = image.getWidth();
this.heightAllRows = image.getHeight();
this.widthOneFrame = this.widthAllCols / 13;
this.heightOneFrame = this.heightAllRows / ROW_COUNT;
this.topToBottoms = new Bitmap[COL_COUNT];
this.rightToLefts = new Bitmap[COL_COUNT];
this.leftToRights = new Bitmap[COL_COUNT];
this.bottomToTops = new Bitmap[COL_COUNT];
imageResized = Bitmap.createScaledBitmap(getMoveBitmaps()[0], 300, 300, false);
}
(...)
public void draw(Canvas canvas) {
imageResized = Bitmap.createScaledBitmap(getCurrentMoveBitmap(), 300, 300, false);
// canvas.drawBitmap(imageResized, 0, 0, null);
}
public Bitmap getCurrentMoveBitmap() {
Bitmap[] bitmaps = this.getMoveBitmaps();
return bitmaps[this.colUsing];
}
public Bitmap[] getMoveBitmaps() {
switch (rowUsing) {
case ROW_BOTTOM_TO_TOP:
return this.bottomToTops;
case ROW_RIGHT_TO_LEFT:
return this.rightToLefts;
case ROW_TOP_TO_BOTTOM:
return this.topToBottoms;
case ROW_LEFT_TO_RIGHT:
return this.leftToRights;
default:
return null;
}
}

You are creating a new bitmap and allocating new memory for it every time you call
Bitmap#createScaledBitmapinsideCharacterCreator#draw. ReassigningimageResizedmakes previously stored bitmap available for GC, so it gets collected in the next GC wave. You have basically two options for improving:imageResizedsomewhere else, then create new bitmap only when yourgetCurrentMoveBitmap()changed. If possible, do it outside ofdrawfunction, as it causes jank.imageResizedjust for drawing, then draw your bitmap directly usingCanvas#drawBitmap(Bitmap,Rect,Rect,Paint). It avoids memory allocations completely. You can do it like this: