android从UIThread获取数据

tez*_*tez 3 android

我试图发送数据的Android使用Arduino的来Bluetooth.我的GUI含有一套SeekBar的和加速度计readings.All Sockets成功形成,如果我写数据到每一件事工作正常OutputStreamSocketonSeekBarChanged()方法,以便数据将被转移到Arduino的时候我改变了SeekBar.

 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        if(seekBar.getId() == R.id.seekBar)
        {
            speed.setText(String.valueOf(progress));
            String outputData = String.valueOf(progress)+",";
            try
            {
            streams.write(outputData.getBytes());//writes data to OutputStream of Socket
            }catch (Exception e){
                Log.d("RTR","Sockets not yet formed");
            }

        }
    }
Run Code Online (Sandbox Code Playgroud)

问题是我需要Accelerometer连续发送数据和SeekBar当前值.所以我试着写一下加速度计OutputStreamSocketfrom onSensorChanged(SensorEvent event)方法.Result:Program not responding.

public void onSensorChanged(SensorEvent event) {

        if(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
        {
            float accXYZ[] = event.values;

            float accX = accXYZ[0];
            float accY = accXYZ[1];
            float accZ = accXYZ[2];

            x.setText(String.format("%.2f",accX));
            y.setText(String.format("%.2f",accY));
            z.setText(String.format("%.2f",accZ));

            String outputData = x.getText().toString()+","+speed.getText().toString()+";";

            try{
                  streams.write(outputData.getBytes());
            }catch (Exception e){
                //Log.d("RTR","X");
            }

        }
    }
Run Code Online (Sandbox Code Playgroud)

我明白这太重载了UI Thread.我想我应该new Threadrun()方法中创建一个无限循环来连续发送数据.我怎么能连续地将加速度计和SeekBar数据发送到这个新线程.

或者我应该从这个新线程收集UIThread的加速度计和SeekBar的数据.

In Short, how do I get data from UIThread to this new Thread.
Run Code Online (Sandbox Code Playgroud)

请提供您对我的问题所了解的所有可能的解决方案以及我当前程序的任何复杂情况.

Bar*_*end 6

一个很好的方法是使用内置Looper类.Looper是支持Android UI线程的消息排队系统,您也可以将它与您自己的线程一起使用.它的设计方式有什么好处,它创建了非常少的垃圾收集负载(取决于你使用的参数类型,它可以是没有).

我正在写这个写意,所以你不得不破解它以使其工作,但这里最终看起来像:

class LooperThread extends Thread {
    private static final int MSG_TYPE_OUTPUT_DATA = 0;
    private Handler mHandler;
    private volatile OutputStream mOutputStream;

    public void run() {
        Looper.prepare();

        mHandler = new Handler() {
            public void handleMessage(Message msg) {
                if (msg.what == MSG_TYPE_OUTPUT_DATA
                    && mOutputStream != null) {
                    //try-catch left out for brevity
                    mOutputStream.write(msg.obj.getBytes());
                }
            }
        };

        Looper.loop();
    }

    public void submitReading(String outputData) {
        mHandler.sendMessage(mHandler.obtainMessage(MSG_TYPE_OUTPUT_DATA, outputData);
    }
}
Run Code Online (Sandbox Code Playgroud)

您的设置代码将执行以下操作:

private void setup() {
    Socket sock = setupBluetoothConnection();
    this.looperThread = new LooperThread();
    this.looperThread.setOutputStream(sock.getOutputStream());
    this.looperThread.start();
}
Run Code Online (Sandbox Code Playgroud)

最后,传感器事件处理程序:

public void onSensorChanged(SensorEvent event) {

    if(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
    {
        // snip...
        String outputData = x.getText().toString()+","+speed.getText().toString()+";";

        this.looperThread.submitReading(outputData);
    }
}
Run Code Online (Sandbox Code Playgroud)

这给你的是一个后台线程,它尽可能快地处理消息,并且你可以从任何其他线程以线程安全的方式提交消息.它们按顺序处理.

完成后,您需要注意正确关闭looper线程,并确保它可以处理套接字连接丢失.

如果你需要将其限制为每秒一定的消息速率,事情会变得复杂一些.OutputStream.write是一个阻塞操作,所以为了方便,我把它留了下来.您要做的是System.nanoTime()在实例字段中注册您上次处理消息的内容,并在handleMessage()方法内,每当下一条消息进入足够的时间之前,您需要计算您需要等待的时间.处理消息.这比使用sendMessageDelayed()在"提交"端处理它要容易得多.