Learning Java by Building Android Games
上QQ阅读APP看书,第一时间看更新

Structuring our code for Android

If you have ever used an Android device, you have probably noticed that it works quite differently from many other operating systems. For example, you are using an application—say you're checking what people are doing on Facebook. Then you get an e-mail notification and you tap the e-mail icon to read it. Midway through reading the e-mail, you might get a Twitter notification and because you're waiting on important news from someone you follow, you interrupt your e-mail reading and change the app to Twitter with a touch.

After reading the tweet, you fancy a game of Angry Birds, but midway through the first daring fling, you suddenly remember that Facebook post. So you quit Angry Birds and tap the Facebook icon.

Then you resume Facebook, probably at the same point you left it. You could have resumed reading the e-mail, decided to reply to the tweet, or started an entirely new app. All this backwards and forwards takes quite a lot of management on the part of the operating system, apparently independent from the individual apps themselves.

The difference between a Windows PC and Android in the context we have just discussed is that with Android, although the user decides which app they are using, the Android OS decides if and when to actually close down (destroy) an application. We just need to consider this when coding our games.

Life cycle phases – what we need to know

The Android system has different phases that any given app can be in. Depending on the phase, the Android system determines how the app is viewed by the user or whether it is viewed at all. Android has these phases so that it can decide which app is in current use and then allocate the right amount of resources such as memory and processing power. But also allow us as game developers to interact with these phases. What if someone quits our game to answer a phone call? Will they lose their progress?

Android has a fairly complex system that, when simplified a little for the purpose of explanation, ensures that every app on an Android device is in one of the following phases:

  • Being created
  • Starting
  • Resuming
  • Running
  • Pausing
  • Stopping
  • Being destroyed

The list of phases will hopefully appear fairly logical. As an example, the user presses the Facebook app icon and the app is created. Then it is started. All are fairly straightforward so far but next in the list is resuming! It is not as illogical as it might first appear if, for a moment, we can just accept that the app resumes after it starts, and then all will become clear as we proceed.

After resuming, the app is running. This is when the Facebook app has control over the screen and probably the greater share of system memory and processing power. Now what about our example where we switched from the Facebook app to the e-mail app?

As we tap to go to read our e-mail, the Facebook app will probably have entered the paused phase, and the e-mail app will enter the being created phase followed by resuming and then running. If we decide to revisit Facebook, as in the scenario earlier, the Facebook app will probably then go straight to the resume phase and then running again, most likely exactly on the post where we left it.

Note that at any time, Android can decide to stop or destroy an app, in which case, when we run the app again, it will need to be created all over again. So had the Facebook app been inactive long enough or had Angry Birds required so many system resources that Android would have destroyed the Facebook app, then our experience of finding the exact post we were previously reading might have been different.

Now, if all this phase stuff is starting to get confusing, then you will be pleased to know that the only reasons to mention are as follows:

  • You know it exists
  • We occasionally need to interact with it
  • We will take things step by step when we do

Life cycle phases – what we need to do

When we are making games, how do we possibly interact with this complexity? The good news is that the Android code that was autogenerated when we created our first project does most of the interaction for us.

All we have to do as game developers is make sure that Android knows what to do with our app in each phase when it happens. Even more good news is that all of these phases are handled by default, unless we override the default handling.

This means we can go ahead with learning Java and making games until we come to one of the few instances where we need to do something in our game, specifically in one of the phases.

Dividing our game into activities

The Java code that we write will be divided into sections or parts called activities. We can think of activities as different screens for our game. For example, during the book, we will often create an activity for a home screen, an activity for the game screen and an activity for the high score screen.

Each activity will have its own life cycle and will be further divided into parts that will correspond to (go into) one of the Android phases we just discussed. The parts in Java are known as methods. Methods are a significant concept in Java programming.

At this stage, however, all we need to know is that methods are used to compartmentalize the Java code we write and that some methods are provided by the Android system so that we can easily handle the otherwise complex Android life cycle.

The forthcoming list is a quick explanation of the methods provided by Android for our convenience, to manage the phases of the life cycle. To clarify our discussion of life cycle phases methods are listed next to their corresponding phases that we have been discussing. However, as you will see, the method names make it fairly clear on their own where they fit in.

In the list, there is also a brief explanation or suggestion about when we should use a given method and thereby interact during a specific phase. We will meet most of these methods as we progress through the book. We will see the onCreate method later in this chapter. Here is the list:

  • onCreate: This method is executed when the activity is being created. Here we get everything ready for the game, including graphics, sound, and perhaps the high scores.
  • onStart: This method is executed when the app is in the starting phase.
  • onResume: This method runs after onStart but can also be entered, perhaps most logically, after our activity is resumed after being previously paused. We might reload a previously saved game situation when the app had been interrupted, perhaps by a phone call or the user running another app.
  • onPause: This occurs when our app is pausing. Here we might want to save the current game. You are probably getting the hang of these methods.
  • onStop: This relates to the stopping phase. This is where we might undo everything we did in onCreate. If we reach here, our activity will probably get destroyed sometime soon.
  • onDestroy: This is when our activity is finally being destroyed—our last chance to dismantle our game. If we reach here, we will definitely be going through the phases of the life cycle from the beginning again.

All the method descriptions and their related phases should appear straightforward. Perhaps, the only real question is about the running phase. As we will see, when we write our code in other methods/phases, the onCreate, onStart, and onResume methods will prepare the game, which persists, forming the running phase. The onPause, onStop, and onDestroy methods will occur afterwards. Now we can actually take a look at one of these methods and some other methods as well.