我正在写一个flutter应用程序,我试图将一些数据插入到本地数据库中,给予数据库创建的主键,但不知何故,await
关键字破坏了处理数据库交互的函数。(下面的代码是我的实际代码的简化版本,但具有所有的要点和相同的问题)
1.Future<int> insertObjekt(Objekt o) async {
2. final db = await _database;
3. return db.insert('objekt', {'name': o.name});
4.}
如果我在第2行和第3行中设置断点,第2行会按预期停止,但在恢复时,程序永远不会在第3行停止(我让它运行了近15分钟,以确保没有发生任何事情)。
1. class TestState extends ChangeNotifier {
2. var db = tempDB;
3. Objekt? currentObjekt;
4.
5. TestState(){
6. initialize('doesn\'t work');
7. /*Objekt o = Objekt.loaded(1, 'in constructor');
8. db.insertObjekt(o);
9. debugPrint('${o.id}');
10. currentObjekt = o;// */
11. //currentObjekt = Objekt('functions as intended', db);
12. while(currentObjekt == null){
13. sleep(const Duration(milliseconds: 10));
14. }
15. debugPrint('concluded');
16. notifyListeners();
17. }
18.
19. Future<void> initialize(String name) async {
20. Objekt o = Objekt.loaded(1, name);
21. o.id = await db.insertObjekt(o);
22. debugPrint('${o.id}');
23. currentObjekt = o;
24. }
25.}
如果我删除第21行中的o.id = await
,它就可以工作。问题是,我需要在这里返回值。第7-10行用于插入和忽略返回值,但是一旦我尝试查询(另一个与insertObject
相同的函数,只是使用db.query和所需类的强制转换),我就需要再次返回值。遍历对象本身也有同样的问题(尽管由于某种原因,当遍历对象时,返回值工作得很好,我可以在类中设置属性)。
当运行应用程序时,它只是停留在一个无休止的加载屏幕上,尽管while循环结束,第15行打印到控制台。我认为这可能是因为await
'创建'了一个新线程,但是如果一个新线程意味着返回值丢失,那么我认为使用cnc-await没有任何意义。为什么函数insertObjekt
在一行之后就停止了,如何确保我得到了想要的返回值,这样数据库就可以被读取了?
编辑以添加:_database的请求实现
1. Future<bool> openDB() async {
2. _database = openDatabase(
3. join(await getDatabasesPath(), 'tappDB.db'),
4. onCreate: (db, version) async {
5. db.execute('''
6. CREATE TABLE objekt(
7. id INTEGER PRIMARY KEY,
8. name TEXT
9. )''');
10. debugPrint("DB built");
11. },
12. version: 4,
13. );
14. debugPrint("DB opened");
15. return true;
16.}
1条答案
按热度按时间x7yiwoj41#
当运行应用程序时,它只是停留在一个无休止的加载屏幕上,尽管while循环结束,第15行打印到控制台。
这是不合理的与此代码。
sleep
blocks,因此您的循环将永远不允许该隔离中的异步操作取得任何进展。即使异步操作在不同的隔离中运行,循环隔离也永远没有机会设置currentObjekt
。(另见stackoverflow.com/a/56707357)。我认为这可能是因为
await
'创建'一个新线程.不,
await
不会创建任何新线程。Dart隔离是单线程的。await
简单地 * 产生 ;它是语法糖,用于返回Future
并为您注册完成回调。循环似乎试图使异步操作同步;在Dart中没有支持的方法来执行此操作。 不要在构造函数中执行异步工作。* If you need to do asynchronous initialization, replace the constructor with a
static
factory method:注意,
initialize
方法现在可能是多余的,可以合并到createTestState
中。还要注意的是,异步操作具有内在的传染性,因此任何需要等待TestState
对象被构造的函数也需要是异步的,并且调用这些函数的任何东西都需要是异步的,等等。