【发布时间】:2026-01-19 09:35:02
【问题描述】:
更新(2020 年 7 月 15 日)
mFeinstein 的回应,目前,是给我第一个可接受的解决方案的唯一答案。
问题
我不得不问你做我想做的事情的最佳方法是什么:
- 以异步模式调用 Web 服务
- 解析响应
- 执行海量数据库操作
所有这些都没有冻结进度动画,比如不确定的进度条。
第一点和第二点没有问题。问题出现在第三个地方,当大量数据库插入正在运行时。而且我还不明白实现这些东西的正确方法是什么。
一些用于澄清的伪代码
UI(显示对话框并运行进度条...)
void callWS() async {
MyProgressDialog _dialog = DialogHelper.showMyProgressDialog(_context, "Data", "Loading...");
await getDataFromService();
_dialog.close();
}
CONNECTION(进度条上不会出现冻结)
static Future<void> getDataFromService() async {
String uri = MY_URI;
String wsMethod = MY_WS_METHOD;
String wsContract = MY_WS_CONTRACT;
SoapObject myRequest = SoapObject.fromSoapObject(namespace: my_namespace, name: wsMethod);
MyConnectionResult response = await _openMyConnection(myRequest, uri, wsContract, wsMethod);
if (response.result == MyResultEnum.OK) {
await _parseResponse(response.data);
}
}
DATABASE(在进度条上发生冻结)
static Future<void> _parseResponse(xml.XmlElement elements) async {
Database db = await MyDatabaseHelper.openConnection();
db.transaction((tx) async {
Batch batch = tx.batch();
for (xml.XmlElement oi in elements.children) {
int id = int.parse(oi.findElements("ID").first.text);
String name = oi.findElements("NAME").first.text;
DatabaseHelper.insertElement(
tx,
id: id,
name: name,
);
}
batch.commit(noResult: true);
});
}
不能替代
我也看到了“计算”函数方法,但是当我调用 db 操作时,sqflite package 似乎有问题。例如:
static Future<void> performDelete() async {
Database db = await openMyConnection();
compute(_performDeleteCompute, db);
}
static void _performDeleteCompute(Database db) async {
db.rawQuery("DELETE MYTABLE");
}
Console error:'
-> Unhandled Exception: Exception: ServicesBinding.defaultBinaryMessenger was accessed before the binding was initialized.
-> If you are running an application and need to access the binary messenger before runApp() has been called (for example, during plugin initialization),
then you need to explicitly call the WidgetsFlutterBinding.ensureInitialized() first.
-> error defaultBinaryMessenger.<anonymous closure> (package:flutter/src/services/binary_messenger.dart:76:7)
#1 defaultBinaryMessenger (package:flutter/src/services/binary_messenger.dart:89:4)
#2 MethodChannel.binaryMessenger (package:flutter/src/services/platform_channel.dart:140:62)
#3 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:146:35)
#4 MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:329:12)
#5 invokeMethod (package:sqflite/src/sqflite_impl.dart:17:13)
#6 SqfliteDatabaseFactoryImpl.invokeMethod (package:sqflite/src/factory_impl.dart:31:7)
#7 SqfliteDatabaseMixin.invokeMethod (package:sqflite_common/src/database_mixin.dart:287:15)
#8 SqfliteDatabaseMixin.safeInvokeMethod.<anonymous closure> (package:sqflite_common/src/database_mixin.dart:208:43)
#9 wrapDatabaseException (package:sqflite/src/exception_impl.dart:7:32)
#10 SqfliteDatabaseFactoryImpl.wrapDatabaseException (package:sqflite/src/factory_impl.dart:27:7)
#11 SqfliteDatabaseMixin.safeInvokeMethod (package:sqflite_common/src/database_mixin.dart:208:15)
#12 SqfliteDatabaseMixin.txnRawQuery.<anonymous closure> (package:sqflite_common/src/database_mixin.dart:394:36)
#13 SqfliteDatabaseMixin.txnSynchronized.<anonymous closure> (package:sqflite_common/src/database_mixin.dart:327:22)
#14 BasicLock.synchronized (package:synchronized/src/basic_lock.dart:32:26)
#15 SqfliteDatabaseMixin.txnSynchronized (package:sqflite_common/src/database_mixin.dart:323:33)
#16 SqfliteDatabaseMixin.txnRawQuery (package:sqflite_common/src/database_mixin.dart:393:12)
#17 SqfliteDatabaseExecutorMixin._rawQuery (package:sqflite_common/src/database_mixin.dart:126:15)
#18 SqfliteDatabaseExecutorMixin.rawQuery (package:sqflite_common/src/database_mixin.dart:120:12)
#19 DatabaseHelper._performDeleteCompute(package:flutter_infocad/Database/DatabaseHelper.dart:368:8)'
并且按照错误日志中的建议,在 runApp() 中首先显式调用 WidgetsFlutterBinding.ensureInitialized(),但没有任何反应。
【问题讨论】:
-
您是否尝试过在不等待的情况下链接调用? like db.openConnection().then() 请从WS调用一路尝试
-
我会试一试,但是,“then”实现回调,“await”是一种“等待结束然后继续”。在第一种情况下,进度条很快到达终点,它不会等待。在第二种情况下,所有操作都以串行方式执行,等待每个操作的返回值。假设您有 10 个操作。首先显示进度条。然后等待10个结论。以隐藏进度条结束。相反,在第二种情况下,您必须显示进度条,通过回调并行启动 10 个操作。跟踪每一个回调结果,当所有操作返回时,隐藏进度条
-
但是,我认为问题是在主线程上运行的大量操作。这就是为什么我尝试使用“计算”功能,但没有成功。
-
请检查这个文档medium.com/flutter-community/… 它说等待可能会阻塞主线程。最好隐含回调
-
这也可能有助于blog.usejournal.com/…
标签: sqlite flutter dart-async dart-isolates