我正在尝试了解使用HandlerThread
的最佳用例。
根据定义:
"用于启动具有looper的新线程的便捷类。然后可以使用looper来创建处理程序类。请注意,仍必须调用start()。"
我可能错了,但是我可以通过使用Thread
、Looper
和Handler
来实现类似的功能。那么何时应该使用HandlerThread
呢?一个示例会非常有帮助。
我正在尝试了解使用HandlerThread
的最佳用例。
根据定义:
"用于启动具有looper的新线程的便捷类。然后可以使用looper来创建处理程序类。请注意,仍必须调用start()。"
我可能错了,但是我可以通过使用Thread
、Looper
和Handler
来实现类似的功能。那么何时应该使用HandlerThread
呢?一个示例会非常有帮助。
onPreviewFrame()
回调函数中接收到它们。 文档 解释说:此回调在从 open(int) 调用的事件线程上调用。
通常,这意味着回调将在主线程上调用。 因此,在菜单打开、动画播放或屏幕上打印统计信息时,处理大量像素数组的任务可能会被阻塞。new HandlerThread()
并将 Camera.open()
委托给该线程(我通过 post(Runnable)
来实现,您不需要实现 Handler.Callback
)。Camera.startPreview()
或 Camera.setPreviewCallback()
委托给 HandlerThread。为了安全起见,我在继续主线程(或在更改之前用于调用 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() 线程间通信是不必要的。
更新: 这里将同样的方法应用于加速度计:单独线程中的加速度传感器
Activity.onPause()
中释放相机-首先,因为这是根据Activity生命周期系统保证您的活动接收到的唯一回调。但是,在onPause()
之后有时可以使用相机。在这种情况下,您需要在不同的场景中优雅地处理它。 - Alex Cohnnotify()
覆盖中执行的操作。 - Alex Cohn这里有一个链接,可以访问 HandlerThread 和 Looper 的源代码。
如果你看这两个源代码,你会发现 HandlerThread
正如它所说的一样 - 它是启动带有 Looper
的 Thread
的方便方法。为什么会有它?因为线程默认没有消息循环。 HandlerThread
只是创建一个具有消息循环的线程的简单方法。从源代码来看,你能用 Handler
,Thread
和 Looper
来复制这个函数吗?答案是可以。
Executor
是不同的。 Executor
接收提交的可运行任务并执行它们。为什么需要这样做呢?这允许你将任务的执行与其实际内容分离。什么时候需要这样做呢?比如说,如果你有一个需要同时执行多个任务的情况。你可以选择使用 Executor
在单个线程上运行它们,以便它们被串行执行。或者你可以使用固定的线程池,以使一些任务并行执行而其他任务不是。在任何情况下,任务的内容 - 即它实际上正在做什么 - 与它的执行方式是分离的。