67

我试图了解使用的最佳用例HandlerThread

根据定义:

“用于启动具有 looper 的新线程的便捷类。然后可以使用 looper 创建处理程序类。请注意,仍然必须调用 start()。”

我可能错了,但我可以通过使用Thread,Looper和来实现类似的功能Handler。那么我应该什么时候使用HandlerThread呢?一个例子真的很有帮助。

4

2 回答 2

87

这是一个现实生活中的例子,其中HandlerThread变得很方便。当您注册相机预览帧时,您会在onPreviewFrame()回调中收到它们。文档解释说这个回调是在事件线程 open(int) 上调用的

通常,这意味着回调将在主 (UI) 线程上调用。因此,当打开菜单、动画动画,甚至在屏幕上打印统计数据时,处理巨大像素阵列的任务可能会卡住。

简单的解决方案是创建一个new HandlerThread()并委托Camera.open()给这个线程(我是通过它完成post(Runnable)的,你不需要实现Handler.Callback)。

请注意,相机的所有其他工作都可以照常完成,您不必委托Camera.startPreview()或委托Camera.setPreviewCallback()给 HandlerThread。为了安全起见,我在继续主线程(或更改之前用于调用的任何线程)之前等待实际完成。Camera.open(int)Camera.open()


所以,如果你从代码开始

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

首先将其按原样提取到私有方法中:

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

而不是调用oldOpenCamera()简单地使用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");
        }
    }
}

请注意,如果打开后不立即访问原始代码中的mCamera ,则整个notify() -- wait()线程间通信是不必要的。

更新:这里同样的方法适用于加速度计:Acclerometer Sensor in separate Thread

于 2013-10-03T08:33:40.867 回答
15

这是HandlerThreadLooper的源代码链接。

如果您查看这两个,您会发现 aHandlerThread正是它所说的 - 一种方便的方式来启动Thread具有 a 的 a Looper。为什么会存在这种情况?因为线程,默认情况下没有消息循环。这HandlerThread只是一种简单的方法来创建一个。你能用Handler,Thread和复制这个函数吗Looper- 从源代码来看 - 答案是肯定的。

Executor不一样。AnExecutor接受提交的可运行任务并 - 猜猜是什么 - 执行它们。为什么这是必要的?它允许您将任务的执行与其实际内容分离。你什么时候用这个?假设您遇到需要同时执行多个任务的情况。您可以选择使用Executor, 在单个线程上运行它们,以便它们连续执行。或者你可以使用一个固定的线程池,这样一些,但不是所有的同时运行。在任何一种情况下,任务的实质——即它实际在做什么——都与它正在执行的方式是分开的。

于 2013-08-09T18:12:57.730 回答