等待传感器数据 android - 我们总是需要一个新线程吗?
Wait for sensor data android - do we always need a new thread?
我有一个简单的 Android 应用程序,它应该在特定时间间隔从传感器获取多个读数。
我目前有两个线程:
UI 启动序列的线程(通过向工作线程处理程序发送消息),并跟踪其状态(无论我是在进行第一次测量,还是重复测量测量)。
工作线程,在后台运行并通过主线程处理程序与主线程通信。
我的意图是将所有关于何时进行测量的逻辑保留在主 UI 线程中(那些是简单的数字比较,没有耗时的工作,因此应该适合 UI线程),并设置一个工作线程作为一个线程,它只知道如何响应从传感器读取数据的请求以及读取结果return。
我的问题出在这个工作线程中。它通过消息接收进行测量的请求,并在其 handleMessage 方法中处理此请求:
public boolean handleMessage(Message msg) {
if (msg.what == StartMeasurementCmd) {
Log.d(TAG, "Starting measurement");
// register sensor event listener
// wait for onSensorChanged
// unregister sensor event listener
Log.d(TAG, "Measurement finished");
// Notify UI thread via uiHandler
Message newMsg = uiHandler.obtainMessage();
newMsg.what = DoneMeasurementCmd;
// add whatever information is needed to the newMsg
newMsg.setTarget(uiHandler);
newMsg.sendToTarget();
}
return false;
}
这里 StartMeasurementCmd 和 DoneMeasurementCmd 是简单的常量。
一旦工作线程接收到测量数据的请求,它需要注册一个传感器侦听器(上面第一行注释),但是它需要等待直到读数可用(上面第二行注释)。读取可用后,它将注销侦听器(上面第三行注释),并向 UI 线程发送消息以通知新数据可用。
我可以想到两种方式来填写第二个注释行:
- 我可以在另一个线程中进行读取(然后简单地使用 wait() 来同步这个工作线程)——基于这两篇文章:
Android sensor registerListener in a separate thread
A method for waiting for sensor data
- 或者,我可以在注册侦听器后简单地放置一个 while 循环,并检查我可以在 onSensorChanged 方法中跳闸的标志。由于工作线程在后台 运行 应该可以阻止它,但我不喜欢我正在使用 "busy" 等待这一事实。
我的问题是 - 有没有办法在同一个工作线程中获取读数,但不执行 "busy" 在 while 循环中等待?还是以上方法中的一种实际上是推荐的方法?
谢谢!
如果我没理解错的话,阻塞工作线程是可以的。然后你不需要一个单独的线程,使侦听器对象成为 monitor(即使用 synchronized
方法)并等待它就足够了。
例如,(粗略勾勒出实际数据的处理方式):
class ListenerMonitor implements WhateverListenerInterface {
private boolean gotData;
... some variable(s) to record the actual data
public synchronized void onSensorChanged(...) {
...
gotData=true;
notifyAll();
}
public synchronized SuitableReturnType readSensor(...) throws InterruptedException {
// register sensor event listener
gotData = false;
while(!gotData) wait();
// unregister sensor event listener
return the data?
}
}
并在工作线程中使用它:
...
ListenerMonitor listenerMonitor = new ListenerMonitor(...);
...
public boolean handleMessage(Message msg) {
if (msg.what == StartMeasurementCmd) {
Log.d(TAG, "Starting measurement");
... = listenerMonitor.readSensor(...);
Log.d(TAG, "Measurement finished");
我有一个简单的 Android 应用程序,它应该在特定时间间隔从传感器获取多个读数。
我目前有两个线程:
UI 启动序列的线程(通过向工作线程处理程序发送消息),并跟踪其状态(无论我是在进行第一次测量,还是重复测量测量)。
工作线程,在后台运行并通过主线程处理程序与主线程通信。
我的意图是将所有关于何时进行测量的逻辑保留在主 UI 线程中(那些是简单的数字比较,没有耗时的工作,因此应该适合 UI线程),并设置一个工作线程作为一个线程,它只知道如何响应从传感器读取数据的请求以及读取结果return。
我的问题出在这个工作线程中。它通过消息接收进行测量的请求,并在其 handleMessage 方法中处理此请求:
public boolean handleMessage(Message msg) {
if (msg.what == StartMeasurementCmd) {
Log.d(TAG, "Starting measurement");
// register sensor event listener
// wait for onSensorChanged
// unregister sensor event listener
Log.d(TAG, "Measurement finished");
// Notify UI thread via uiHandler
Message newMsg = uiHandler.obtainMessage();
newMsg.what = DoneMeasurementCmd;
// add whatever information is needed to the newMsg
newMsg.setTarget(uiHandler);
newMsg.sendToTarget();
}
return false;
}
这里 StartMeasurementCmd 和 DoneMeasurementCmd 是简单的常量。
一旦工作线程接收到测量数据的请求,它需要注册一个传感器侦听器(上面第一行注释),但是它需要等待直到读数可用(上面第二行注释)。读取可用后,它将注销侦听器(上面第三行注释),并向 UI 线程发送消息以通知新数据可用。 我可以想到两种方式来填写第二个注释行:
- 我可以在另一个线程中进行读取(然后简单地使用 wait() 来同步这个工作线程)——基于这两篇文章:
Android sensor registerListener in a separate thread
A method for waiting for sensor data
- 或者,我可以在注册侦听器后简单地放置一个 while 循环,并检查我可以在 onSensorChanged 方法中跳闸的标志。由于工作线程在后台 运行 应该可以阻止它,但我不喜欢我正在使用 "busy" 等待这一事实。
我的问题是 - 有没有办法在同一个工作线程中获取读数,但不执行 "busy" 在 while 循环中等待?还是以上方法中的一种实际上是推荐的方法?
谢谢!
如果我没理解错的话,阻塞工作线程是可以的。然后你不需要一个单独的线程,使侦听器对象成为 monitor(即使用 synchronized
方法)并等待它就足够了。
例如,(粗略勾勒出实际数据的处理方式):
class ListenerMonitor implements WhateverListenerInterface {
private boolean gotData;
... some variable(s) to record the actual data
public synchronized void onSensorChanged(...) {
...
gotData=true;
notifyAll();
}
public synchronized SuitableReturnType readSensor(...) throws InterruptedException {
// register sensor event listener
gotData = false;
while(!gotData) wait();
// unregister sensor event listener
return the data?
}
}
并在工作线程中使用它:
...
ListenerMonitor listenerMonitor = new ListenerMonitor(...);
...
public boolean handleMessage(Message msg) {
if (msg.what == StartMeasurementCmd) {
Log.d(TAG, "Starting measurement");
... = listenerMonitor.readSensor(...);
Log.d(TAG, "Measurement finished");