We'll again build on the work in the previous threading tutorials but this time make the application more real world by splitting the threads off into their own classes. We do this to make them more manageable, and we'll add another background thread to make the planets spin around behind all the counters.
The planets are defined in their own class and rotate around a fixed point. Their direction is also random - its defined when they are first created.
We create a new Thread object to rotate the Planets, called appropriately enough the RotationThread. This is going to be started at the beginning of the app and run constantly, alongside the Counter updating thread. The Planets are really nothing more than Bitmaps placed in certain positions on the View. To rotate them, the RotationThread just maintains a counter from 0 to 360, incremented every 100ms. When it gets to 360, it starts again at 0. Those numbers are no accident: there is specific functionality in Androids Canvas class to support rotation, and this uses an argument passed in as a value in degrees.
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(100);
} catch (Exception e) {}
// Update the ticker
mThreading3View.setRotation(mThreading3View.getRotation() + 1);
if (mThreading3View.getRotation() >= 360) {
mThreading3View.setRotation(0);
}
/*
* If there are no counters present then there are no messages
* being sent to update the display, so the planets won't move.
* If there are any, we don't want to waste resources by firing off
* redundant update messages
*/
if (mThreading3View.getCounterPositions().size() == 0) {
// Cause the display to update
Message msg = Message.obtain();
msg.arg1 = Threading3View.MSG_UPDATE;
mThreading3View.getHandler().sendMessageDelayed(msg,
Threading3View.MSG_UPDATE);
}
}
}
Recall from Threading2 that we must never make a UI call from a thread other than the main one. So, when these rotation values are updated we use the same technique as before: we send the main View a message, in this case MSG_UPDATE. The View then handles it by calling invalidate(), which in turn causes the onDraw() method to be called. When this goes through the list of Planets to be drawn, it will use the updated rotation values and so the Planets will appear to move: