And in that order please.
One of the great things about Java, and by extension Android is the garbage collector. For those of you who don’t know, this will periodically sweep through your application and free any objects that you can’t access any more. Very, very handy, but there is a problem with it: in order to get a consistent view of your application, it has to stop your application. Normally this only takes a moment but if you are scrolling through a set of pictures which are going out of scope as they flow off the top of the screen the garbage collector will periodically freeze your application to clean up and cause the scrolling to stutter slightly.
The way to avoid this is to keep the number of discarded objects to a minimum.
Looking at our view we can see examples of unnecessary creation and subsequent discarding of objects.
The first two examples are the paint objects defined in drawBoard(). We are using two paint objects to draw squares side by side to create the chess board pattern, however we can make a single call to drawColor() to fill the entire view one colour and then use the other paint object to draw the alternating squares to achieve the same effect.
This reduces the number of objects we create by one, saving instantiation and clean-up time for that object. The remaining paint object is defined in the drawBoard() function and so will be discarded and replaced with a new paint object every time the view redraws itself. We can stop this from happening by declaring the paint object at the class level and setting it’s colour when the view is created.
//Board.java
public Board(Context context, AttributeSet attrs) {
super(context, attrs);
mDark.setColor(Color.parseColor("#AAAA88"));
}
private Paint mDark = new Paint();
private void drawBoard(Canvas canvas) {
canvas.drawColor(Color.parseColor("#FFFFAA"));
for (int i = 0; i < 8 ; i++) {
for (int j = 0; j < 8 ; j++) {
if ((i+j) % 2 == 0)
canvas.drawRect(j * mTileWidth , i * mTileHeight , (j+1) * mTileWidth , (i+1) * mTileHeight, mDark);
}
}
}
Now the paint object will never be go out of scope as long as the view is active so we reuse the same one for every call of onDraw(), saving another set of instantiation and clean-up times. This is also why the undo() function reuses the mCurrentMove object rather than discarding and creating new ones each time.
Finally, when the user hits undo, the Move object in the undo stack goes out of scope at the end of the function. While we could build a complimentary stack of undone history, this seems overly complex so we’ll just let the Move object drift out of scope and let the garbage collector recycle it into empty space for something else to use. While the garbage collector will sto our game to do it, this is likely to happen at time when nothing else is moving so the user will not see it.