Best use of HandlerThread over other similar classes

旧城冷巷雨未停 提交于 2019-11-25 22:46:06

问题


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.


回答1:


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




回答2:


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.



来源:https://stackoverflow.com/questions/18149964/best-use-of-handlerthread-over-other-similar-classes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!