Better use of HandlerThread over other similar classes

I am trying to figure out the best use HandlerThread .

According to the definition:

"A convenient class for starting a new thread that has a looper. Then you can use a looper to create handler classes. Note that start () still needs to be called.

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

+58
android android-handler
Aug 09 '13 at 15:10
source share
2 answers

Here is a real life example when HandlerThread becomes convenient. When you register in the camera preview frame, you get them in the onPreviewFrame() . The documentation explains that this callback is called in the open (int) event stream called from .

This usually means that the callback will be called in the main thread (UI). Thus, the task of working with huge arrays of pixels may depend on opening the menu, animating the animation, or even with statistics printed on the screen.

A simple solution is to create new HandlerThread() and delegate Camera.open() to this thread (I did this via post(Runnable) , you do not need to implement Handler.Callback ).

Please note that all other work with the camera can be performed as usual, you do not need to delegate Camera.startPreview() or Camera.setPreviewCallback() to HandlerThread. To be safe, I expect Camera.open(int) to actually complete before continuing with the main thread (or some 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 in 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() just 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"); } } } 

Please note that the whole chain of notify () - wait () is not required if you do not get access to mCamera in the source code immediately after opening it.

Update: Here the same approach applies to the accelerometer: The accelerometer sensor in a separate topic

+70
Oct 03 '13 at 8:33
source share

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

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

An Executor is different. Executor accepts the assigned runnable tasks and - guesses what -executes them. Why is this necessary? This allows you to separate the execution of the task from its actual substance . When do you use this? Suppose you had a situation that required several tasks to be performed simultaneously. You can choose, using Executor , to run them all in one thread, so that they run in serial. Or you can use a fixed thread pool so that some, but not all, start at the same time. In any case, the essence of the task — that is, what it actually does — is separated from how it is carried out.

+14
Aug 09 '13 at 18:12
source share



All Articles