The following is the first few sections of a chapter from The Busy Coder's Guide to Android Development, plus headings for the remaining major sections, to give you an idea about the content of the chapter.


Anti-Patterns

Much of this book has been focused on what you should do. In contrast, this chapter is focused on what you should not do.

All platforms have their anti-patterns: things that are technically possible but are not in the best interests of the users of that platform. Android is no exception. Some anti-patterns are simply annoying to users, while other anti-patterns can significantly infringe upon a user’s use of their Android device, or even the user’s freedom.

Much as the Hippocratic Oath directs doctors to “first, do no harm”, Android application developers owe it to the users of their apps to avoid these anti-patterns to the greatest extent possible.

Prerequisites

This chapter assumes that you have read much of the book, particularly the core chapters.

Leak Threads… Or Things Attached to Threads

Leaking a thread means that you start a thread and never cause it to stop. For example, you might start a thread that runs in an infinite loop, doing some work and then sleeping for a while. The problem with infinite loops is that “infinite” is an awfully long time.

All threads should clean up, in a timely fashion, when the component (e.g., activity, service) that started the thread is destroyed — or, in the case of an activity, perhaps just moved into the background.

How you ensure that the thread gets cleaned up is up to you. For threads doing transactional work, such as literally running a database transaction, it may be fine to just let them run to completion and shut down of their own accord. For “infinite” loops, there should be some way to tell the thread that it is no longer needed, such as via an AtomicBoolean flag, or using something more structured than a plain timing loop, such as a ScheduledExecutorService.

Also, bear in mind that you are responsible for threads that are created, on your behalf, by other things that you do. The most common leak scenario here comes with listeners associated with system services, like LocationManager and SensorManager. If you register a LocationListener via requestLocationUpdates() and fail to unregister that listener, you will not only be leaking the listener, but the component associated with that listener, and every system resource tied to that listener, such as any background threads.

The Costs

Threads are intrinsically static in scope. Hence, any object they can reach, directly or indirectly, cannot be garbage-collected while the thread is still running. Hence, if an activity forks a thread, it might do so using an anonymous inner class:

new Thread() {
  public void run() {
    // do something
  }
}).start();

Instances of an inner class — anonymous or otherwise — have an implicit reference back to the object that created them. Hence, the Thread would hold onto the Activity that created the thread, which in turn would hold onto all of its widgets and so forth. None of that can be garbage-collected until after the thread terminates, even if the activity is destroyed.

The Counter-Arguments

I want the thread to keep running even after the activity is destroyed

In this case, the thread should be created and managed by a service, not simply leaked. Not only does this give you an opportunity to clean up the thread when needed, but it also alerts Android that you are still trying to do some work, so Android will not necessarily terminate your process very quickly.

However, be careful about assuming that you can have a thread — even one managed by a service — run forever, as you will see in the next couple of sections.

I do not know when the thread is no longer needed

Then you have a serious design problem.

A common variation on this theme is:

The thread is needed so long as I have an activity in the foreground

This is a bit tricky, as Android does not really expose the concept of applications being in the foreground, just activities.

The safest course of action is to have the thread be managed by a service, then keep track of whether or not you have an activity in the foreground. For example, in onPause() of each activity, use postDelayed() to return control to you after a short delay, and in onResume(), update a timestamp of your last return to the foreground (held in a static data member). When the Runnable for postDelayed() executes, check that timestamp — if it is too old, you know that none of your activities are in the foreground, and you can stop the service, having it stop your thread.

Use Large Heap Unnecessarily

The preview of this section apparently resembled a Pokémon.

Misuse the MENU Button

The preview of this section was last seen in the Bermuda Triangle.

Interfere with Navigation

The preview of this section is unavailable right now, but if you leave your name and number at the sound of the tone, it might get back to you (BEEEEEEEEEEEEP!).

Use android:sharedUserId

The preview of this section apparently resembled a Pokémon.

Implement a “Quit” Button

The preview of this section will not appear here for a while, due to a time machine mishap.

Terminate Your Process

The preview of this section was last seen in the Bermuda Triangle.

Try to Hide from the User

The preview of this section was fed to a gremlin, after midnight.

Use Multiple Processes

The preview of this section was traded for a bag of magic beans.

Hog System Resources

The preview of this section was abducted by space aliens.