gpt4 book ai didi

flutter) Bluetooth provider error =>setState() or markNeedsBuild() 在构建过程中被调用

转载 作者:行者123 更新时间:2023-12-05 06:49:02 41 4
gpt4 key购买 nike

我正在尝试使用 flutter_Blue 开发“BLE Con​​trol App”。我添加了一个标签栏,所以我想保持蓝牙状态“连接”。所以我正在尝试使用 Provider 来设置连接状态,但我遇到了这样的错误。

**======== Exception caught by foundation library ====================================================
The following assertion was thrown while dispatching notifications for BluetoothProvider:
setState() or markNeedsBuild() called during build.
This _InheritedProviderScope<BluetoothProvider> widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was: _InheritedProviderScope<BluetoothProvider>
value: Instance of 'BluetoothProvider'
listening to value
The widget which was currently being built when the offending call was made was: Consumer<BluetoothProvider>
dirty
dependencies: [_InheritedProviderScope<BluetoothProvider>]
When the exception was thrown, this was the stack:
#0 Element.markNeedsBuild.<anonymous closure> (package:flutter/src/widgets/framework.dart:4138:11)
#1 Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:4153:6)
#2 _InheritedProviderScopeElement.markNeedsNotifyDependents (package:provider/src/inherited_provider.dart:531:5)
#3 ChangeNotifier.notifyListeners (package:flutter/src/foundation/change_notifier.dart:243:25)
#4 BluetoothProvider.startScan (package:flutter_joystick/provider/bluetooth_provider.dart:46:5)
...
The BluetoothProvider sending notification was: Instance of 'BluetoothProvider'**

这是我的蓝牙提供商代码

class BluetoothProvider with ChangeNotifier{
final String SERVICE_UUID = "0000ffe0-0000-1000-8000-00805f9b34fb";
final String CHARACTERISTIC_UUID="0000ffe1-0000-1000-8000-00805f9b34fb";
final String TARGET_DEVICE_NAME="HMSoft";

FlutterBlue flutterBlue = FlutterBlue.instance;
StreamSubscription<ScanResult> scanSubScription;

BluetoothDevice targetDevice;
BluetoothCharacteristic targetCharacteristic;
BluetoothState bluetoothState;

String connectionText="";
String joystick="";

startScan(){

connectionText="Start Scanning";

scanSubScription = flutterBlue.scan().listen((scanResult){
if(scanResult.device.name==TARGET_DEVICE_NAME){
print("Device Found");

stopScan();


connectionText="Found Target Device";

targetDevice = scanResult.device;
}
}, onDone: () => stopScan());
notifyListeners();
}
stopScan(){
scanSubScription?.cancel();
scanSubScription=null;
notifyListeners();
}

connectToDevice() async{
if(targetDevice==null) return;

connectionText = "Device Connecting";

await targetDevice.connect();
print("Device Connected");

connectionText="Device Connected";


discoverServices();
notifyListeners();
}

disconnectFromDevice(){
if(targetDevice==null) return;
targetDevice.disconnect();

connectionText="Device Disconnected";

notifyListeners();
}

discoverServices() async{

if(targetDevice==null) return;

List<BluetoothService> services = await targetDevice.discoverServices();
services.forEach((service) {

if(service.uuid.toString() == SERVICE_UUID){
service.characteristics.forEach((characteristc) {
if (characteristc.uuid.toString() == CHARACTERISTIC_UUID) {
targetCharacteristic = characteristc;
writeData("Connect Complete!\r\n");

connectionText = "All Ready with ${targetDevice.name}";

}

});
}

}
);
notifyListeners();
}
writeData(String data) async{
if(targetCharacteristic==null) return;
List<int> bytes = utf8.encode(data);
await targetCharacteristic.write(bytes);
notifyListeners();
}
}

有趣的是,蓝牙连接正在进行,但上面写的错误不断通过控制台窗口出现。

Tab Bar第一页是摇杆页面,蓝牙连接出错,摇杆不工作。

这是操纵杆代码

class JoyPad extends StatefulWidget {
@override
_JoyPadState createState() => _JoyPadState();
}

class _JoyPadState extends State<JoyPad> {
BluetoothProvider _bluetoothProvider;

@override
Widget build(BuildContext context) {
_bluetoothProvider = Provider.of<BluetoothProvider>(context,listen:false);
return Consumer<BluetoothProvider>(
builder:(context,provider,child) {
_bluetoothProvider.startScan();
return Scaffold(
appBar: AppBar(
title: Text(_bluetoothProvider.connectionText),
backgroundColor: Colors.indigoAccent,
actions: <Widget>[
IconButton(
icon: Icon(Icons.bluetooth), iconSize: 30,
onPressed: () {
_bluetoothProvider.connectToDevice();
print(_bluetoothProvider.bluetoothState.toString());
},
),
IconButton(
icon: Icon(Icons.bluetooth_disabled), iconSize: 30,
onPressed: () {
_bluetoothProvider.disconnectFromDevice();
print(_bluetoothProvider.bluetoothState.toString());
}),
],
),
body: joystickWidget(),
);
});

}
}

此外,提供者没有“setState”,所以我尝试根据 App Bar 上的状态变化显示连接文本,但这是不可能的。如果你能告诉我如何解决它,我也将不胜感激。

最佳答案

您实际上遇到此错误是因为您在构建小部件树时尝试重建它。

您的电话 _bluetoothProvider.startScan();在您的消费者的构建器方法中将调用 notifyListeners方法在构建树时实际尝试重建树,因此将抛出该异常。

为什么?Consumer 小部件实际上正在监听您的 BluetoothProvider 上的变化;所以当你在 BluetothProvider 上调用 notifyListeners 时类,Consumer 试图重建自己,这是未经授权的。

解决方案是先构建树,然后调用 startScan 方法。

你可以试试这个:

提供商代码

class BluetoothProvider with ChangeNotifier{
final String SERVICE_UUID = "0000ffe0-0000-1000-8000-00805f9b34fb";
final String CHARACTERISTIC_UUID="0000ffe1-0000-1000-8000-00805f9b34fb";
final String TARGET_DEVICE_NAME="HMSoft";

FlutterBlue flutterBlue = FlutterBlue.instance;
StreamSubscription<ScanResult> scanSubScription;

BluetoothDevice targetDevice;
BluetoothCharacteristic targetCharacteristic;
BluetoothState bluetoothState;

String connectionText="";
String joystick="";

startScan() {
connectionText="Start Scanning";

scanSubScription = flutterBlue.scan().listen((scanResult){
if(scanResult.device.name==TARGET_DEVICE_NAME){
print("Device Found");

stopScan();
connectionText="Found Target Device";
targetDevice = scanResult.device;
}
}, onDone: () => stopScan());
notifyListeners();
}

stopScan() {
scanSubScription?.cancel();
scanSubScription=null;
notifyListeners();
}

connectToDevice() async{
if(targetDevice==null) return;

connectionText = "Device Connecting";

await targetDevice.connect();
print("Device Connected");

connectionText="Device Connected";
discoverServices();
notifyListeners();
}

disconnectFromDevice(){
if(targetDevice==null) return;
targetDevice.disconnect();

connectionText="Device Disconnected";
notifyListeners();
}

discoverServices() async {
if(targetDevice==null) return;

List<BluetoothService> services = await targetDevice.discoverServices();
services.forEach((service) {

if(service.uuid.toString() == SERVICE_UUID){
service.characteristics.forEach((characteristc) {
if (characteristc.uuid.toString() == CHARACTERISTIC_UUID) {
targetCharacteristic = characteristc;
writeData("Connect Complete!\r\n");

connectionText = "All Ready with ${targetDevice.name}";
}
});
}
});
notifyListeners();
}

writeData(String data) async{
if(targetCharacteristic==null) return;

List<int> bytes = utf8.encode(data);
await targetCharacteristic.write(bytes);
notifyListeners();
}
}

小部件代码

class JoyPad extends StatefulWidget {
@override
_JoyPadState createState() => _JoyPadState();
}

class _JoyPadState extends State<JoyPad> {

@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
// The code in this block will be executed after the build method
context.read<BluetoothProvider>().startScan();
});
}

@override
Widget build(BuildContext context) {
return Consumer<BluetoothProvider>(
builder:(context,provider,child) {
return Scaffold(
appBar: AppBar(
title: Text(_bluetoothProvider.connectionText),
backgroundColor: Colors.indigoAccent,
actions: <Widget>[
IconButton(
icon: Icon(Icons.bluetooth), iconSize: 30,
onPressed: () {
_bluetoothProvider.connectToDevice();
print(_bluetoothProvider.bluetoothState.toString());
},
),
IconButton(
icon: Icon(Icons.bluetooth_disabled), iconSize: 30,
onPressed: () {
_bluetoothProvider.disconnectFromDevice();
print(_bluetoothProvider.bluetoothState.toString());
},
),
],
),
body: joystickWidget(),
);
});
}
}
}

context.read<BluetoothProvider>().startScan();Provider.of<BluetoothProvider>(context, listen: false).startScan() 的快捷方式: 它基本上做同样的事情。

关于flutter) Bluetooth provider error =>setState() or markNeedsBuild() 在构建过程中被调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66669648/

41 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com