我试图了解使用的最佳用例HandlerThread
。
根据定义:
“用于启动具有 looper 的新线程的便捷类。然后可以使用 looper 创建处理程序类。请注意,仍然必须调用 start()。”
我可能错了,但我可以通过使用Thread
,Looper
和来实现类似的功能Handler
。那么我应该什么时候使用HandlerThread
呢?一个例子真的很有帮助。
我试图了解使用的最佳用例HandlerThread
。
根据定义:
“用于启动具有 looper 的新线程的便捷类。然后可以使用 looper 创建处理程序类。请注意,仍然必须调用 start()。”
我可能错了,但我可以通过使用Thread
,Looper
和来实现类似的功能Handler
。那么我应该什么时候使用HandlerThread
呢?一个例子真的很有帮助。
这是一个现实生活中的例子,其中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
这是HandlerThread和Looper的源代码链接。
如果您查看这两个,您会发现 aHandlerThread
正是它所说的 - 一种方便的方式来启动Thread
具有 a 的 a Looper
。为什么会存在这种情况?因为线程,默认情况下没有消息循环。这HandlerThread
只是一种简单的方法来创建一个。你能用Handler
,Thread
和复制这个函数吗Looper
- 从源代码来看 - 答案是肯定的。
安Executor
不一样。AnExecutor
接受提交的可运行任务并 - 猜猜是什么 - 执行它们。为什么这是必要的?它允许您将任务的执行与其实际内容分离。你什么时候用这个?假设您遇到需要同时执行多个任务的情况。您可以选择使用Executor
, 在单个线程上运行它们,以便它们连续执行。或者你可以使用一个固定的线程池,这样一些,但不是所有的同时运行。在任何一种情况下,任务的实质——即它实际在做什么——都与它正在执行的方式是分开的。