Author: G. Blake Meike
Publisher: Addison Wesley
Audience: Android developers ready for a "deep dive"
Reviewer: Mike James
Concurrency is the biggest barrier to implementing a stable Android program and a good book on the topic is well overdue.
Android programming is difficult. It is more difficult than programming a desktop machine because there are so many additional considerations. One of the biggest problems is that the user interface (UI) is single-threaded and to do anything useful you have to employ additional threads to do the work. This is a common situation for a desktop app as well, but for the mobile app you also have to cope with the problem of being suspended and completely destroyed by the operating system. Android apps can be removed from memory at any time to keep the mobile phone working. When they are brought back into memory the operating system doesn't fully restore their state and the result is that threads can be lost, or not re-created, and this causes bugs that actually show themselves so rarely that you think that they might be hardware faults.
To create a high quality Android program you have to understand how concurrency works and how it can go horribly wrong. The first chapter is a very brief introduction to concurrency and the sort of things that can happen if two threads make use of the same resource.
Chapter 2 builds on these general ideas and applies them to Java threads in particular. Here we meet the Java Thread class and synchronization primitives. The treatment is fairly fast paced and if you haven't encountered the ideas before you are probably going to need some additional reading. What is more likely to happen is that you won't notice that you haven't got the full picture because there aren't enough examples of how things work and don't work. As always in books on Java concurrency, the idea of locking on an object isn't really explained. Why lock on "this" for example? You are just left to work it out for yourself and I don't think its obvious. I also found the explanations often didn't go to the heart of the matter. For example, there is a long discussion of the visibility of variables between threads and the meaning of the volatile keyword. Yet nowhere does it simply say that volatile means that the variable might change its value due to influences not in the immediate code. That is, a volatile variable can change due to other threads or hardware and hence the compiler has to make sure that an access takes this into account and doesn't just consider changes caused by the code running on the current thread. It also doesn't mention the fact the that volatile keyword ensures that all changes to variables made by a thread before writing to a volatile variable are made available to other threads.
There is also a tendency to present the same program in its entirety again even if there is only a minor change. This means you can't actually see that the change is there without looking hard.
Chapter 3 tackles the seriously difficult question of the lifecycle. There is a good discussion of how things are set up when an app runs, along with a convincing justification of why the UI is simpler for being single- threaded.
Chapter 4, Async Tasks and Loaders, is where the work of the book really begins - everything before is scene setting. These are classes added by Android to make concurrency easier and many Android programmers learn about AsyncTask and never use anything else. We have a reasonable explanations of AsyncTask followed by some musings on the use of the threadpool. No explanation of what the threadpool is or how you should think about what is going on. This "talking around" the problem continues though the rest of the book, which is fine if you already know a lot but not if you are a beginner. The AsyncTask is heavily criticised for being a dangerous construct, but when you analyse what the problems are they are simply the standard problems of working with more than one thread.
Chapter 5 moves on to explain the Looper/Handler, which is Android's implementation of an event or message loop. I found the explanation of how it all works not particularly helpful because it gets too deep before you have had time to understand the basics.
Chapter 6 explains services and interprocess communication. Again this goes too deep to quickly and spends a lot of time talking round the topic. The penultimate chapter deals with periodic tasks, using Timer, Alarm manager, sync-adapter, JobScheduler and so on. The final chapter looks at some tools that might make the problem easier.
Overall I feel that there is a lot in this book that will confuse the beginner, but I find myself in the position of having to recommend it. There just aren't enough books on this important topic and even a book that isn't as clear as it could be is worth reading.
At the end of reading it you might not know the best way to implement concurrency and you might even have some irrational dislikes of perfectly good ways of doing it just because there is no perfect way. You are also likely to pick up a vague feeling that what looks like perfectly good code isn't because of some deep a lurking flaw that you haven't spotted, but this is better than not being aware that concurrency is the number one Android problem.
To keep up with our coverage of books for programmers, follow @bookwatchiprog on Twitter or subscribe to I Programmer's Books RSS feed for each day's new addition to Book Watch and for new reviews.