You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 15:10:00