Flutter - 为什么我会收到“未处理的异常:迭代期间并发修改”从数据库查询?
我在理解有关颤振数据库处理的问题时遇到了一些困难(至少我这么认为,因为这就是问题所在)。当我运行我的应用程序时,我收到以下错误消息:
E/flutter (26185): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: Concurrent modification during iteration: Instance(length:13) of '_GrowableList'.
E/flutter (26185): #0 ListIterator.moveNext (dart:_internal/iterable.dart:336:7)
E/flutter (26185): #1 _MyHomePageState._processBle.<anonymous closure> (package:blescanner/screens/home_view.dart:283:27)
E/flutter (26185): <asynchronous suspension>
我花了很多精力试图找出原因。引用的第 283 行是 MyHomePage 中的“for (var element in list){”行,但据我所知,我并没有尝试在任何地方修改该列表。一段时间后,我开始逐行注释以查找问题的原因,结果发现当我注释掉“dbHelper.getBlItemLog”调用时,问题消失了。这让我进入了该函数(代码包含在下面),其中问题似乎是数据库查询。我认为这可能是查询期间修改数据库的一些问题,因此我删除了对数据库的所有其他调用,但问题仍然存在。数据库查询怎么会导致这种问题呢?我就是不明白为什么?有人对此有什么见解或建议吗?
来自 MyHomePage(扩展了 Stateful Widget):
void _processBle() {
FlutterBluePlus.instance.scanResults.forEach((list) async {
for (var element in list) {
String bleName = element.device.name;
dev.log('Found device: ' + bleName);
String blItemId = bleName.replaceAll('XXX', '');
var blItemData = CustomBluetoothItem.fromBle(bleName,
blItemId,
element.advertisementData.manufacturerData,
_geoPos.lat, _geoPos.long
);
int tempStatus = blItemData.status;
try {
if (blItemData.status > 1) {
await lock.synchronized(() async {
dev.log('${DateTime.now()
.toIso8601String()} _processBle .. start $bleName');
//here's where I call the troubling function
await dbHelper.getBlItemLog(
bleName: bleName, startDate: blItemData.sDate)
.then((queueItem) async {
// the stuff in here is commented away for now and thus doesn't matter
});
dev.log('${DateTime.now()
.toIso8601String()} _processBle .. stop ${element.device
.name}');
});
}
} catch (e) {
dev.log('error : $e');
}
}
});
firstStartup = false;
dev.log('_processBle - ### done');
}
来自我的 dbHelper:
Future<CustomBluetoothItem?> getBlItemLog({required String bleName, required String startDate}) async {
Database? db = await database;
//the following line seems to be where the issue is, since there's no issue if I comment it away.
List<Map<String, dynamic>> maps = await db!.rawQuery('SELECT * FROM ble_table WHERE bleName = ? AND startDate = ? ORDER BY createDate desc limit 1 offset 0',[bleName,startDate]);
if (maps.isNotEmpty) {
return CustomBluetoothItem.fromJson(maps[0]);
}
return null;
}
I'm having some trouble understanding an issue regarding flutters database handling (at least I assume so since that's where the issue seems to be). When I run my app I get the following error message:
E/flutter (26185): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: Concurrent modification during iteration: Instance(length:13) of '_GrowableList'.
E/flutter (26185): #0 ListIterator.moveNext (dart:_internal/iterable.dart:336:7)
E/flutter (26185): #1 _MyHomePageState._processBle.<anonymous closure> (package:blescanner/screens/home_view.dart:283:27)
E/flutter (26185): <asynchronous suspension>
I've put a lot of effort trying to find why this is. The row 283 referenced is my "for (var element in list){"-row in MyHomePage, but to my knowledge I'm not trying to modify that list anywhere. After some time I just started commenting away line after line to find what the cause of the issue and it turns out that it disappeared when I commented away the "dbHelper.getBlItemLog"-call. That led me into that function (code included further down) where the issue seems to be the database query. I thought that it might be some issue with the database being modified during the query, so I removed all other calls to the database, but the issue remained. How can a database query cause this kind of issue? I just can't understand why? does anyone have any kind of insight or suggestion regarding this?
from MyHomePage (which extends Stateful Widget):
void _processBle() {
FlutterBluePlus.instance.scanResults.forEach((list) async {
for (var element in list) {
String bleName = element.device.name;
dev.log('Found device: ' + bleName);
String blItemId = bleName.replaceAll('XXX', '');
var blItemData = CustomBluetoothItem.fromBle(bleName,
blItemId,
element.advertisementData.manufacturerData,
_geoPos.lat, _geoPos.long
);
int tempStatus = blItemData.status;
try {
if (blItemData.status > 1) {
await lock.synchronized(() async {
dev.log('${DateTime.now()
.toIso8601String()} _processBle .. start $bleName');
//here's where I call the troubling function
await dbHelper.getBlItemLog(
bleName: bleName, startDate: blItemData.sDate)
.then((queueItem) async {
// the stuff in here is commented away for now and thus doesn't matter
});
dev.log('${DateTime.now()
.toIso8601String()} _processBle .. stop ${element.device
.name}');
});
}
} catch (e) {
dev.log('error : $e');
}
}
});
firstStartup = false;
dev.log('_processBle - ### done');
}
from my dbHelper:
Future<CustomBluetoothItem?> getBlItemLog({required String bleName, required String startDate}) async {
Database? db = await database;
//the following line seems to be where the issue is, since there's no issue if I comment it away.
List<Map<String, dynamic>> maps = await db!.rawQuery('SELECT * FROM ble_table WHERE bleName = ? AND startDate = ? ORDER BY createDate desc limit 1 offset 0',[bleName,startDate]);
if (maps.isNotEmpty) {
return CustomBluetoothItem.fromJson(maps[0]);
}
return null;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论