等待传感器数据android - 我们总是需要一个新线程吗?

Posted

技术标签:

【中文标题】等待传感器数据android - 我们总是需要一个新线程吗?【英文标题】:Wait for sensor data android - do we always need a new thread? 【发布时间】:2015-07-17 13:52:51 【问题描述】:

我有一个简单的 android 应用程序,它应该以特定的时间间隔从传感器获取多个读数。 我目前有两个线程:

    启动序列(通过向工作线程处理程序发送消息)并跟踪其状态(我是在进行第一次测量还是重复测量)的 UI 线程。

    工作线程,在后台运行,通过主线程处理程序与主线程通信。

我的意图是将所有关于何时进行测量的逻辑保留在主 UI 线程中(这些是简单的数字比较,没有耗时的工作,所以应该适合 UI 线程),并设置一个工作线程作为一个只知道如何响应从传感器读取数据的请求并返回读取结果的线程。

我的问题在于这个工作线程。它通过消息接收进行测量的请求,并在其 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方法中跳闸的标志。由于工作线程在后台运行,应该可以阻止它,但我不喜欢我使用“忙”等待的事实。

我的问题是 - 有没有办法在同一个工作线程中获取读数,但无需在 while 循环中进行“忙碌”等待?还是上述方法之一实际上是推荐的方法?

谢谢!

【问题讨论】:

【参考方案1】:

如果我理解正确,可以阻塞工作线程。那么你就不需要一个单独的线程,将监听器对象设置为 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");

【讨论】:

感谢您的建议。由于 listenerMonitor 和 readSensor 都在同一个线程中,wait() 调用不会阻止 listenerMonitor 执行其 onSensorChanged 方法吗? 不,wait() 在阻塞之前释放锁,然后确保在调用返回之前重新获取锁(在调用notify() 之后)。

以上是关于等待传感器数据android - 我们总是需要一个新线程吗?的主要内容,如果未能解决你的问题,请参考以下文章

Android传感器的使用

android怎么判断线程池的任务等待

请求后台任务在 Android 中多次运行

接近唤醒锁并不总是重新打开屏幕

Android 传感器开发详解

玩转Android之加速度传感器的使用,模仿微信摇一摇