如何解决Flutter中的bad state: element error问题?
求助:Flutter开发中遇到bad state: element error错误
我是Flutter和Android Studio新手,开发应用时遇到bad state: element error错误,试过网上的解决方案没用,求帮忙!
错误提示详情:
Bad state: No element
触发位置:PositioningSystem._handleScanResults方法中调用firstWhere查找匹配的AnchorDistance时未找到对应元素
相关代码文件
myapp.dart
import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:path_finder/routing.dart'; import 'package:path_finder/routingWidget.dart'; import 'package:provider/provider.dart'; import 'location.dart'; import 'locationWidget.dart'; import 'map_widget.dart'; import 'mock_positioning_system.dart'; import 'positioning_system.dart'; import 'user_position.dart'; import 'user_position_widget.dart'; class MyApp extends StatefulWidget { final PositioningSystem positioningSystem; final UserPosition userPosition; final Routing routing; const MyApp(this.positioningSystem, this.userPosition, this.routing, {Key? key}) : super(key: key); @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { final List<MapWidget> _mapWidgets = [ const MapWidget(imagePath: 'assets/E02.png'), const MapWidget(imagePath: 'assets/E03.png'), const MapWidget(imagePath: 'assets/E04.png'), ]; int _currentFloor = 0; bool _isLocationSearchVisible = false; Location? _selectedLocation; @override void initState() { super.initState(); widget.positioningSystem.start(); } @override void dispose() { widget.positioningSystem.stop(); super.dispose(); } void _updateSelectedLocation(Location location) { setState(() { _selectedLocation = location; _isLocationSearchVisible = false; }); } @override Widget build(BuildContext context) { SystemChrome.setPreferredOrientations([ DeviceOrientation.portraitUp, DeviceOrientation.portraitDown, ]); return MultiProvider( providers: [ ChangeNotifierProvider.value(value: widget.userPosition), ChangeNotifierProvider.value(value: widget.positioningSystem), ], child: MaterialApp( home: Scaffold( body: Container( width: 400, height: 565, child: Stack( children: [ _mapWidgets[_currentFloor], if (_selectedLocation != null && _selectedLocation!.z / 100 - 1 == _currentFloor) const UserPositionWidget(), Visibility( visible: _isLocationSearchVisible, child: LocationSearch( widget.routing, _updateSelectedLocation ), ), if (_selectedLocation != null && !_isLocationSearchVisible && _selectedLocation!.z / 100 - 1 == _currentFloor) Opacity( opacity: 0.2, child: RoutingWidget( routing: widget.routing, path: widget.routing.getShortestPath(_selectedLocation!), destinationName: _selectedLocation!.name, ), ), if (!_isLocationSearchVisible) Positioned( bottom: 0, left: 20, child: DropdownButton<int>( value: _currentFloor, items: const [ DropdownMenuItem( value: 0, child: Text('Floor 2'), ), DropdownMenuItem( value: 1, child: Text('Floor 3'), ), DropdownMenuItem( value: 2, child: Text('Floor 4'), ), ], onChanged: (value) { setState(() { _currentFloor = value!; }); }, ), ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: () { setState(() { _isLocationSearchVisible = !_isLocationSearchVisible; }); }, child: const Icon(Icons.search), ), ), ), ); } }
positioning_system.dart
import 'package:flutter/cupertino.dart'; import 'package:flutter_blue/flutter_blue.dart'; import 'package:vector_math/vector_math.dart'; import 'anchor.dart'; import 'ble_manager.dart'; import 'distance_computation.dart'; import 'trilateration.dart'; import 'user_position.dart'; import 'package:device_info/device_info.dart'; import 'package:flutter/services.dart'; import 'dart:io' show Platform; class PositioningSystem extends ChangeNotifier { final BLEManager _bleManager = BLEManager(); late final List<AnchorDistance> _anchorDistances = [ AnchorDistance(id: 'anchor1_1', x: 0, y: 0, z: 100, distance: 0), AnchorDistance(id: 'anchor1_2', x: 0, y: 100, z: 100, distance: 0), AnchorDistance(id: 'anchor1_3', x: 200, y: 300, z: 100, distance: 0), AnchorDistance(id: 'anchor2_1', x: 0, y: 0, z: 200, distance: 0), AnchorDistance(id: 'anchor2_2', x: 0, y: 100, z: 200, distance: 0), AnchorDistance(id: 'anchor2_3', x: 200, y: 300, z: 200, distance: 0), AnchorDistance(id: 'anchor3_1', x: 0, y: 0, z: 300, distance: 0), AnchorDistance(id: 'anchor3_2', x: 0, y: 100, z: 300, distance: 0), AnchorDistance(id: 'anchor3_3', x: 200, y: 300, z: 300, distance: 0), ]; String _beaconId = 'beacon_id'; final UserPosition _userPosition; PositioningSystem(this._userPosition); Future<String> getDeviceId() async { String androidId = ''; final DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); try { if (Platform.isAndroid) { androidId = await deviceInfo.androidInfo.then((value) => value.androidId); } } on PlatformException catch (e) { print('Error getting device ID: $e'); } return androidId; } void start() { print('Start Scanning...'); getDeviceId().then((value) { _beaconId = value; print('beacon id: $_beaconId'); }); _bleManager.startScan(); _bleManager.scanResults.listen(_handleScanResults); } void stop() { _bleManager.stopScan(); } void _handleScanResults(List<ScanResult> results) { print('results length: ${results.length}'); for (ScanResult result in results) { print(result.device.id.toString()); if (result.device.id.toString() == _beaconId) { double distance = DistanceComputation.calculateDistance(result.rssi, -50); String anchorId = result.device.name; AnchorDistance anchorDistance = _anchorDistances.firstWhere((ad) => ad.id == anchorId); anchorDistance.distance = distance; print('distance: $distance'); print('rssi: ${result.rssi}'); } } Vector3? position = calculatePosition(); if (position != null) { _userPosition.setX(position.x); _userPosition.setY(position.y); _userPosition.setZ(position.z); } notifyListeners(); } Vector3? calculatePosition() { List<AnchorDistance> filteredAnchors = _anchorDistances.where((ad) => ad.distance != 0).toList(); if (filteredAnchors.length < 3) { return null; } HyperTrilateration trilateration = HyperTrilateration(filteredAnchors); trilateration.compute(); double x = trilateration.getX(); double y = trilateration.getY(); double z = trilateration.getZ(); return Vector3(x, y, z); } void dispose() { _bleManager.stopScan(); } List<AnchorDistance> get anchorDistances => _anchorDistances; }
错误原因及解决方案
错误原因
问题出在PositioningSystem._handleScanResults方法的这行代码:
AnchorDistance anchorDistance = _anchorDistances.firstWhere((ad) => ad.id == anchorId);
当扫描到的设备名称(result.device.name)不在预定义的_anchorDistances列表的id集合中时,firstWhere找不到匹配元素就会抛出Bad state: No element错误。
解决方案
修改firstWhere的调用逻辑,添加orElse参数处理找不到元素的情况,避免崩溃:
// 替换原查找代码 AnchorDistance? anchorDistance = _anchorDistances.firstWhere( (ad) => ad.id == anchorId, orElse: () => null, ); // 仅找到匹配项时更新距离 if (anchorDistance != null) { anchorDistance.distance = distance; print('distance: $distance'); print('rssi: ${result.rssi}'); } else { print('未找到匹配的锚点ID: $anchorId'); }
额外优化:增加设备名称为空的判断,避免无效查找:
if (result.device.id.toString() == _beaconId) { if (result.device.name.isEmpty) { print('设备名称为空,跳过处理'); continue; } double distance = DistanceComputation.calculateDistance(result.rssi, -50); String anchorId = result.device.name; // 后续查找逻辑... }
内容的提问来源于stack exchange,提问作者randomgamer800
相关产品推荐
相关产品推荐

