flutter - 停止收听流
问题描述
该程序在第一次构建时运行良好。当我断开设备并重新连接时,它显示状态不佳:流已被监听,可能是由监听蓝牙特性的流产生错误。解决方法是什么?
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_blue/flutter_blue.dart';
import 'package:vibration/vibration.dart';
StreamSubscription _scanSubscription;
StreamSubscription _deviceConnection;
Stream<List<int>> stream;
List<double> traceDust = List();
const String CHAR_UUID = "AA:48:F8:CC:07:12";
const String Device_Name = "myDevice";
const String CHARACTERISTIC_UUID = "00000000-0111-1000-4000-000000000000";
BluetoothDeviceState _state;
Map<DeviceIdentifier, ScanResult> scanResults = new Map();
List<BluetoothService> services = new List();
BluetoothCharacteristic characteristic;
FlutterBlue flutterBlue = FlutterBlue.instance;
BluetoothDevice device;
class SearchScreen extends StatefulWidget {
@override
_SearchScreenState createState() => _SearchScreenState();
}
class _SearchScreenState extends State<SearchScreen> {
@override
void initState() {
super.initState();
_startScan();
}
@override
void dispose() {
super.dispose();
_stopScan();
_deviceConnection?.cancel();
_deviceConnection = null;
device.disconnect();
}
_startScan() {
_scanSubscription =
flutterBlue.scan(timeout: Duration(seconds: 4)).listen((scanResult) {
if (CHAR_UUID == scanResult.device.id.toString()) {
_stopScan();
_connect(scanResult.device);
print('connected');
}
}, onDone: _stopScan());
}
_stopScan() {
_scanSubscription?.cancel();
_scanSubscription = null;
}
_connect(BluetoothDevice d) async {
device = d;
await device.connect(autoConnect: true);
await device.discoverServices().then((value) {
setState(() {
services = value;
});
});
_turnOnCharacterService(services);
}
_turnOnCharacterService(List<BluetoothService> ser) async {
ser.forEach((service) {
service.characteristics.forEach((character) {
if (character.uuid.toString() == CHARACTERISTIC_UUID) {
character.setNotifyValue(!character.isNotifying);
setState(() {
stream = character.value;
});
}
});
});
}
String _dataParser(List<int> dataFromDevice) {
return utf8.decode(dataFromDevice);
}
vibrateOnAlert() async {
if (await Vibration.hasVibrator()) {
Vibration.vibrate(duration: 1000);
}
}
@override
Widget build(BuildContext context) {
return Container(
child: StreamBuilder<BluetoothDeviceState>(
stream: device.state,
initialData: BluetoothDeviceState.connecting,
builder: (context, snapshot) {
if (snapshot.data == BluetoothDeviceState.connected) {
return StreamBuilder<List<int>>(
stream: stream,
builder: (context, snapshot) {
var currentValue;
if (snapshot.hasError) {
return Text('Error');
}
if (snapshot.connectionState == ConnectionState.active) {
currentValue = _dataParser(snapshot.data);
traceDust.add(double.tryParse(currentValue) ?? 0);
if (currentValue.toString().compareTo('vibrate') == 0) {
vibrateOnAlert();
}
} else {
return Text('disconnected');
}
print('$currentValue');
return Text('connected');
});
}
return FlatButton(
color: Colors.white,
child: Text('reconnecct'),
onPressed: () {
setState(() {
flutterBlue.startScan(timeout: Duration(seconds: 2));
});
},
);
},
));
}
}
PS:这里的平面按钮什么都不做。由于连接状态是一个流构建器,它会自动重新连接并显示错误。
解决方案
推荐阅读
- php - 如何在自定义函数中获取订单 ID
- c# - 使用多类分类算法在 ML.NET 中进行批量预测
- vba - DoCmd.OpenReport 在某些电脑上运行良好,在其他电脑上不工作(冻结访问)
- python - Flask:动态创建路由
- bigdata - 我可以在 Fuseki 服务器上加载两个单独的 tdb 数据集并一次只查询一个吗?
- laravel - laravel 存储如何检查存储的文件
- sql - 更新列中的值
- javascript - Cheerio js成对获取元素
- flutter - Flutter 中未显示 BottomNavigationBar 标题
- git - git-flow:如何处理从更改到已发布分支的版本号