68

I am trying to understand the best use case of using HandlerThread.

As per definition:

"Handy class for starting a new thread that has a looper. The looper can then be used to create handler classes. Note that start() must still be called."

I may be wrong but similar functionality I can achieve by using a Thread, Looper and Handler. So when should I use HandlerThread? An example would be really helpful.

JonasVautherin
  • 7,297
  • 6
  • 49
  • 95
Androidme
  • 3,145
  • 3
  • 24
  • 27
  • I never used HandlerThread, but maybe this post will help - http://stackoverflow.com/questions/7462098/handlerthread-vs-executor-when-is-one-more-appropriate-over-the-other – Tal Kanel Aug 09 '13 at 15:14
  • 1
    @TalKanel: Thanks for reply. I have checked this post but it talks about benefit of Executor over HandlerThread, which I completely agree. My question is more like what is the best use case to use HandlerThread – Androidme Aug 09 '13 at 15:20
  • That post also addresses this question. Executors are more flexible in that they can manage a pool of threads. Multiple threads - you need to use an Executor. Single thread - you can use a HandlerThread. Not sure it matters since the Executor coulc cover both situations. As I understood it a HandlerThread just allows you to create a handler on a background thread - something that can be done by other means anyway. – Rarw Aug 09 '13 at 15:28
  • See my comment here - http://stackoverflow.com/questions/17897536/how-to-handle-tcp-data/17898322#comment26144902_17898322. In general, I prefer `HandlerThread`s due to the super simple synchronization via `Message`s. That said, it can also be a bottleneck. Also, there's nothing stopping you from using an ExecutorService with HandlerThreads. I've written one before, it's not that difficult. – Delyan Aug 09 '13 at 15:30
  • @Rarw: that was actually my question, if we can do things by other means, what is need to create another class. I am sure there are some benefits in special scenarios, which I need to know. – Androidme Aug 09 '13 at 15:50
  • @bsengar idk if that statement is true in general. There are a lot of examples of things that can be done multiple ways that don't necessarily have a clear benefit. – Rarw Aug 09 '13 at 15:52
  • @Delyan: can you please give an example, or somewhere I can find some code which uses HandlerThread in effective way. The examples I have seen so far are just generic..thanks – Androidme Aug 09 '13 at 15:52
  • @Rarw: Got it...if that is the case, i am fine..thanks – Androidme Aug 09 '13 at 15:53
  • See my answer. I had to dig around but I think this is the distinction you're looking for – Rarw Aug 09 '13 at 18:13
  • @Androidme Here is one example where the Android system uses a HandlerTread to handle clicks to notifications of downloads from the browser: http://androidxref.com/4.4.2_r2/xref/packages/apps/Browser/src/com/android/browser/OpenDownloadReceiver.java – IgorGanapolsky Apr 16 '14 at 17:44
  • @Delyan please can you explain why `HandlerThread` can be a bottleneck as you say? – Jodes Aug 02 '14 at 10:20

2 Answers2

88

Here is a real life example where HandlerThread becomes handy. When you register for Camera preview frames, you receive them in onPreviewFrame() callback. The documentation explains that This callback is invoked on the event thread open(int) was called from.

Usually, this means that the callback will be invoked on the main (UI) thread. Thus, the task of dealing with the huge pixel arrays may get stuck when menus are opened, animations are animated, or even if statistics in printed on the screen.

The easy solution is to create a new HandlerThread() and delegate Camera.open() to this thread (I did it through post(Runnable), you don't need to implement Handler.Callback).

Note that all other work with the Camera can be done as usual, you don't have to delegate Camera.startPreview() or Camera.setPreviewCallback() to the HandlerThread. To be on the safe side, I wait for the actual Camera.open(int) to complete before I continue on the main thread (or whatever thread was used to call Camera.open() before the change).


So, if you start with code

try {
    mCamera = Camera.open(1);
}
catch (RuntimeException e) {
    Log.e(LOG_TAG, "failed to open front camera");
}
// some code that uses mCamera immediately

first extract it as is into a private method:

private void oldOpenCamera() {
    try {
        mCamera = Camera.open(1);
    }
    catch (RuntimeException e) {
        Log.e(LOG_TAG, "failed to open front camera");
    }
}

and instead of calling oldOpenCamera() simply use newOpencamera():

private void newOpenCamera() {
    if (mThread == null) {
        mThread = new CameraHandlerThread();
    }

    synchronized (mThread) {
        mThread.openCamera();
    }
}
private CameraHandlerThread mThread = null;
private static class CameraHandlerThread extends HandlerThread {
    Handler mHandler = null;

    CameraHandlerThread() {
        super("CameraHandlerThread");
        start();
        mHandler = new Handler(getLooper());
    }

    synchronized void notifyCameraOpened() {
        notify();
    }

    void openCamera() {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                oldOpenCamera();
                notifyCameraOpened();
            }
        });
        try {
            wait();
        }
        catch (InterruptedException e) {
            Log.w(LOG_TAG, "wait was interrupted");
        }
    }
}

Note that the whole notify() -- wait() inter-thread communication is not necessary if you don't access mCamera in the original code immediately after opening it.

Update: Here the same approach is applied to accelerometer: Acclerometer Sensor in Separate Thread

Community
  • 1
  • 1
Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
  • 4
    Where would you close the camera then? – Matthias Feb 24 '14 at 08:13
  • 2
    @Matthias: that's a good question. If your use case allows this, release the camera in `Activity.onPause()` - first of all, because this is the _only callback_ that your activity is guaranteed to receive from the system, according to the [Activity lifecycle](http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle). But there are cases when you can use the camera _after_ onPause(). In such case, you need few places, to be graceful in different scenarios. – Alex Cohn Feb 24 '14 at 13:56
  • 1
    The )} closing the new Runnable is supposed to be }) – Rich Mar 23 '14 at 07:17
  • 1
    @Praveen sure, there is nothing sacred about "static" in this context – Alex Cohn Dec 22 '14 at 19:17
  • @AlexCohn is there any way to find when it is safe to take picture I mean when is this Handler going finish its task? I went through handleMessage method but did not get a way to combine with this. – Praveena Dec 24 '14 at 12:39
  • 1
    @Praveen: this is what you can do in your override of `notify()` – Alex Cohn Dec 26 '14 at 21:05
  • I'm trying out the above code but getting a sizable delay in camera.open which is blocking my UI thread – Psest328 Jan 09 '15 at 19:49
  • 1
    @WizardKnight: You are right, `Camera.open()` may be painfully long on some devices. The good practice is to not block on this, but do all possible initializations in parallel, and setup the preview as response to a message from the non-UI thread. Actually, as I mentioned in the post, it is very often that `Camera.open()` is called from a background thread, e.g. via `AsyncTask`, to keep the UI responsive. The sample code that I posted here was resolving a different problem: to show a painless transition from single-thread implementation to `HandlerThread` without changing the logic. – Alex Cohn Jan 11 '15 at 07:53
  • @GopalSinghSirvi: could you please be more specific? – Alex Cohn Jul 29 '15 at 11:08
  • I used to read qr code in onpreview frame method but by this the flash button on the preview frame to turn on and off the flash is working too late after the tap so i read your answer and implemented your code to start camera in separate thread to give some relief to main thread but after doing that still my flash button is not working properly on time, (before qr reading in preview callback everything was ok) – Gopal Singh Sirvi Jul 29 '15 at 11:41
  • 1
    @GopalSinghSirvi: this may deserve a separate question. But without going deeper, "flash" button manipulates camera, and therefore moving the camera to separate thread does not help: you cannot change the flash while camera thread is locked. You should delegate QR code processing to yet another thread, you can use Executor or AsyncTask for that. – Alex Cohn Jul 29 '15 at 19:30
  • Here is my question please try to solve http://stackoverflow.com/questions/31741871/why-continuous-auto-focusing-the-camera-with-handler-dont-allow-to-toggle-camera – Gopal Singh Sirvi Jul 31 '15 at 08:47
  • start() is non-blocking, so getLooper() may return null. – Yaroslav Mytkalyk Jun 29 '16 at 09:38
  • @YaroslavMytkalyk: `start()` here is called on the new thread itself, so it `getLooper()` will be OK. See http://stackoverflow.com/questions/84285/calling-thread-start-within-its-own-constructor; I believe that this specific case (with a private static class that encapsulates the new thread) is a legitimate exception for - otherwise quite sound - arguments in the linked discussion. – Alex Cohn Jun 29 '16 at 10:32
  • @AlexCohn, thanks for the reply, I was wrong, I just had a reply here http://stackoverflow.com/a/25096981/1366471 The `getLooper()` method blocks until the Looper is instantiated in HandlerThread, so for HandlerThread it works. But it's still kind of bad pattern to call start() in constructor. – Yaroslav Mytkalyk Jun 29 '16 at 11:33
15

Here is a link to the source code for HandlerThread and Looper.

If you look at the two you will see that a HandlerThread is exactly what it says it is - a convenient way to start a Thread that has a Looper. Why does this exist? Because threads, by default do not have a message loop. The HandlerThread is just an easy way to create one that does. Could you duplicate this function with Handler, Thread, and Looper - judging from the source code - the answer is yes.

An Executor is different. An Executor takes submitted runnable tasks and - guess what -executes them. Why is this necessary? It allows you to decouple the execution of the task from its actual substance. When would you use this? Say you had a situation that required executing multiple tasks at the same time. You could choose, using an Executor, to run them all on a single thread so that they are executed serialy. Or you could use a fixed thread pool so that some, but not all are run at the same time. In either case the substance of the task - i.e. what it's actually doing - is seperate from the manner in which it is being executed.

TheHippo
  • 61,720
  • 15
  • 75
  • 100
Rarw
  • 7,645
  • 3
  • 28
  • 46
  • 1
    I think your distinction is imprecise. You can submit tasks to be executed via Handler.postRunnable, too. In fact, you can create an ExecutorService that uses only HandlerThreads by just changing the ThreadFactory and submit() methods. It is the cross-thread communication that becomes easier with HandlerThreads, not task submitting. – Delyan Aug 10 '13 at 13:58
  • 1
    I guess I was unclear. I didn't mean to suggest that task execution was easier with an Executor. Rather that the purpose of an Executor is designed to handle only the execution of those tasks. A HandlerThread serves a different purpose. I'll edit it later. – Rarw Aug 10 '13 at 14:27