Chapter 26 Loopers, Handlers, and HandlerThread
For the More Curious: AsyncTasks vs Threads
Now that you understand Handler and Looper, AsyncTask may not seem quite so magical. It is still
less work than what you have done here. So why not use AsyncTask instead of a HandlerThread?
There are a few reasons. The most fundamental one is that AsyncTask is not designed for it. It is
intended for work that is short-lived and not repeated too often. Your code in the previous chapter is
a place where AsyncTask shines. But if you are creating a lot of AsyncTasks or having them run for a
long time, you are probably using the wrong class.
A more compelling technical reason is that in Android 3.2, AsyncTask changed its implementation in
a significant way. Starting with Android 3.2, AsyncTask does not create a thread for each instance of
AsyncTask. Instead, it uses something called an Executor to run background work for all AsyncTasks
on a single background thread. That means that AsyncTasks will run one after the other. A long-
running AsyncTask will hog the thread, preventing other AsyncTasks from getting any CPU time.
It is possible to safely run AsyncTasks in parallel by using a thread pool executor instead, but we do not
recommend doing so. If you are considering doing this, it is usually better to do your own threading,
using Handlers to communicate back to the main thread when necessary.
For the More Curious: Solving the Image Downloading Problem
This book is here to teach you about the tools in the standard Android library. If you are open to using
third-party libraries, though, there are a few libraries that can save you a whole lot of time in various
scenarios, including the image downloading work you implemented in PhotoGallery.
Admittedly, the solution you implemented in this chapter is far from perfect. When you start to need
caching, transformations, and better performance, it is natural to ask whether someone else has solved
this problem before you. The answer is yes: Someone has. There are several libraries available that
solve the image-loading problem. We currently use Picasso (square.github.io/picasso/) for image
loading in our production applications.
Picasso lets you do everything from this chapter in one line:
private class PhotoHolder extends RecyclerView.ViewHolder {
...
public void bindGalleryItem(GalleryItem galleryItem) {
Picasso.with(getActivity())
.load(galleryItem.getUrl())
.placeholder(R.drawable.bill_up_close)
.into(mItemImageView);
}
...
}
The fluent interface requires you specify a context using with(Context). You can specify the URL
of the image to download using load(String) and the ImageView object to load the result into using
into(ImageView). There are many other configurable options, such as specifying an image to display
until the requested image is fully downloaded (using placeholder(int) or placeholder(drawable)).