我正在写一个flutter应用程序,它通过蓝牙(FlutterBlue)向设备发送命令。该设备控制一些LED。通信总体上运行良好,但:在UI上我有一个控制光线强度的滑块。当我拉滑块时,会产生比蓝牙后端所能处理的更多的值。
在我的第一个实现中,我直接将数据发送到蓝牙特性,导致蓝牙后端出现异常,一些值丢失,很难将亮度衰减到零。
在我的第二种方法中,我使用一个流和一个await for
循环来发送数据。现在所有的值都被发送了,没有任何例外,但是在释放滑块后,直到所有的值都被发送需要几秒钟。因为我想在LED上得到直接的视觉反馈,所以这不是一个选项。
由于有多个相同类型的命令要发送,我可以跳过所有相同类型的命令,这些命令是在蓝牙发送例程处理写事件时添加的。
我看到有一个Stream.Distinct
方法,但是:它返回了一个新的流,所以我必须退出await for
循环并处理新的流。
是否有一种方法可以从现有流中删除不需要的事件,而无需创建必须侦听的新流?
我是这么做的:
class MyBlueToothDevice {
BluetoothDevice _device;
List<BluetoothCharacteristic> _characteristics =
List<BluetoothCharacteristic>();
final _sendStream = StreamController<Tuple2<SendCommands, List<int>>>();
MyBlueToothDevice(this._device) {
_writeNext();
}
Future<void> write(SendCommands command, List<int> value) async {
if (isConnected) {
_sendStream.add(Tuple2<SendCommands, List<int>>(command, value));
// await _characteristics[command.index].write(value).catchError((value) {
// print("Characteristics.write error: $value");
// });
}
}
Future<void> _writeNext() async {
await for (var tuple in _sendStream.stream) {
await _characteristics[tuple.item1.index]
.write(tuple.item2)
.catchError((value) {
print("Characteristics.write error: $value");
});
}
}
}
1条答案
按热度按时间pinkon5k1#
最好的解决方案是使用应用程序状态管理来接收来自滑块的所有事件,然后状态管理器将对发送到设备的消息进行速率限制,使其能够处理,并确保最近的消息不会丢失。
一个非常基本的解决方案是接收滑块值并在状态管理器中更新该值,然后一个具有合适速率的周期性计时器可以将该值更新到设备;可能只有在该值自上次发送以来实际改变的情况下。