最好使用HandlerThread而不是其他类似的类
我想了解使用HandlerThread
的最佳用例。
根据定义:
“用于启动一个具有活套的新线程的方便类,活套可用于创建处理程序类,请注意start()仍然必须被调用。
我可能是错的,但类似的功能,我可以通过使用Thread
, Looper
和Handler
来实现。 那么我应该什么时候使用HandlerThread
呢? 一个例子会很有帮助。
HandlerThread变得方便,这是一个真实的例子。 当您注册Camera预览帧时,您将在onPreviewFrame()
回调中收到它们。 文档解释说, 这个回调是在事件线程open(int)被调用时调用的 。
通常,这意味着回调将在主(UI)线程上被调用。 因此,当打开菜单,动画动画时,或者甚至在屏幕上打印统计信息时,处理巨大像素阵列的任务可能会卡住。
简单的解决方案是创建一个new HandlerThread()
并委托Camera.open()
到这个线程(我通过post(Runnable)
,不需要实现Handler.Callback
)。
请注意,使用Camera的所有其他工作都可以照常完成,您不必将Camera.startPreview()
或Camera.setPreviewCallback()
委托给HandlerThread。 为了安全起见,在继续执行主线程(或在更改之前调用Camera.open()
任何线程Camera.open()
之前,我等待实际的Camera.open(int)
完成。
所以,如果你从代码开始
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传感器在分开的线程
这是一个HandlerThread和Looper源代码的链接。
如果你看看两者,你会看到一个HandlerThread
正是它所说的 – 一个启动一个具有Looper
的Thread
的简便方法。 为什么这个存在? 因为线程,默认情况下没有消息循环 。 HandlerThread
只是创建一个简单的方法。 你可以用Handler
, Thread
和Looper
复制这个函数 – 从源代码判断 – 答案是肯定的。
Executor
是不同的。 Executor
接受提交的可运行的任务,并猜测它们是什么。 为什么这是必要的? 它使您可以将任务的执行与其实际内容分离 。 你什么时候用这个? 假设你有一个需要同时执行多个任务的情况。 您可以选择使用Executor
在单个线程上运行它们,以便它们顺序执行。 或者你可以使用一个固定的线程池,以便一些,但不是全部同时运行。 在任何一种情况下,任务的实质 – 即实际上正在做什么 – 都与其被执行的方式分离。