【开发经验】Flutter Blue监听收到重复数据解决办法

前言

FlutterBlueFlutter上最早的蓝牙插件库,为Flutter App提供蓝牙交互的能力,主要资料地址:

GitHub: https://github.com/pauldemarc...
Pub: https://pub.dev/packages/flut...

问题

FlutterBlue的其他部分用起来都很好,代码显得非常易读。但是有一个问题一直伴随着FlutterBlue的使用,在有的项目中,可以忽略这个问题,在有的项目中,这个问题会非常明显的造成逻辑问题,甚至造成整个项目出现问题,那就是重复收到回调问题。

详情

以下是FlutterBlue文档提供的部分使用方法。

Connect to a device

// Connect to the device
await device.connect();

// Disconnect from device
device.disconnect();

Set notifications and listen to changes

await characteristic.setNotifyValue(true);
characteristic.value.listen((value) {
    // do something with new value
});

如果你手动断开你的设备(断电或关闭蓝牙),再按上述代码连接,你会发现// do something with new value处的代码会重复执行,这个问题非常的棘手,似乎限流函数都不对此处起作用。

解决

显然问题就发生在setNotifyValue。在此处,FlutterBlue会注册流,而在自动断开时,并不会取消这个监听,所以,我们需要手动监听device的状态,在断开连接时取消监听:

_connectListenControl = device.state.listen(
  (BluetoothDeviceState newState) {
    if (newState == BluetoothDeviceState.disconnected) {
       // 取消之前的监听函数
       _notifyListenControl?.cancel();
       // 取消监听
      _notify.setNotifyValue(false)
    }
  },
);

看上去似乎有一些反直觉:在设备断开后,还需要去操作设备,去取消设备的监听方法。

只能说这是FlutterBlue本身的设计,这个设计的目的可能在于:在恢复连接时,恢复之前的监听。很显然通常的业务场景并不会设计恢复的操作,而是重新去建立新的连接,所以就造成了重复监听(因为之前的监听还在)。此时,应当手动释放监听。

结语

这也是一个比较顽固的问题,搞了一年才解决,之前都是放着不管。不过我认为这个问题也可能是多方面的,如果按此方法不能解决这个问题,请在评论区告诉我。

作者:马嘉伦
日期:2020/10/16
平台:Segmentfault,勿转载

我的其他文章:

【开发经验】Flutter组件的事件传递与数据控制
【开发经验】Flutter避免代码嵌套,写好build方法

【Flutter工具】fmaker:自动生成倍率切图/自动更换App图标
【Flutter工具】可能是Flutter上最简单的本地数据保存方案
【Flutter应用】Flutter精仿抖音开源