【问题标题】:Using the value returned from a Future in a class in dart在 dart 的类中使用从 Future 返回的值
【发布时间】:2020-04-08 13:56:24
【问题描述】:

你好,我有以下代码

class TodoProvider {
  Database db;


  TodoProvider() {
    _initDatabase();
    print("Db is >>>>> $db");
  }

  void _initDatabase() async {
    final database = await AppDatabase().connect();
    db = database;
  }

  Future<Todo> insertTodo(Todo todo) async {
    todo.id = await db.insert('todo', todo.toMap());
    return todo;
  }

  Future<Todo> getTodo(int id) async {
    List<Map<String, dynamic>> maps =
        await db.query('todo', where: 'id=?', whereArgs: [id]);
    if (maps.length > 0) {
      return Todo.fromMap(maps.first);
    }
    return null;
  }

  Future<int> deleteTodo(int id) async {
    return await db.delete('todo', where: 'id=?', whereArgs: [id]);
  }

  Future<int> updateTodo(Todo todo) async {
    return await db
        .update('todo', todo.toMap(), where: 'id=?', whereArgs: [todo.id]);
  }

  Future close() async => db.close();
}

AppDatabase 是一个公开 connect() 方法的类,该方法返回一个未来。

目标是将 AppDatabase 返回的值赋给 db 类变量

TodoProvider 类中的大多数方法都依赖 db 类变量来处理数据库。

问题是类变量 db 总是为空

【问题讨论】:

  • 当你调用_initDatabase时,它是一个async函数,同时调用await,你必须等待它完成。虽然它没有完成连接,但 db 将始终为 null。也许你试图建立的联系是错误的。尝试更新您的代码并向我们展示数据库的路径、端口、数据库是否正在运行等。
  • @Kohls 如果我要在 TodoProvider 构造方法中等待 _initDatabase 的结果,这将导致错误。如何获取 db 变量来保存来自 AppDatabase().connect() 的数据;
  • 不知道 AppDatabase() 是做什么的,connect() 也不知道,数据不足帮不上忙。

标签: asynchronous dart


【解决方案1】:

您现在的代码取决于正在设置的 db 变量,该变量发生在异步操作中。有两种方法可以解决此问题:

使用静态构建器方法

您可以创建一个可以由静态方法调用的私有构造函数,该方法允许返回Future&lt;TodoProvider&gt;,用户可以等待。

class TodoProvider {
...
  TodoProvider._(this.db) {
    print("Db is >>>>> $db");
  }

  static Future<TodoProvider> getInstance() async {
    return TodoProvider._(await AppDatabase().connect());
  }
...
}

使用 Future 作为类的成员

这不是最漂亮的解决方案,但仍然是一种方法。由于您被允许在同一个Future 上多次await,因此您每次需要访问Database 对象时只需await

class TodoProvider {
  Future<Database> _db;

  TodoProvider() {
    _initDatabase();
    print("Db is >>>>> $db");
  }

  void _initDatabase() {
    _db = AppDatabase().connect();
  }

  Future<Todo> insertTodo(Todo todo) async {
    final db = await _db;
    todo.id = await db.insert('todo', todo.toMap());
    return todo;
  }

  Future<Todo> getTodo(int id) async {
    final db = await _db;
    List<Map<String, dynamic>> maps =
    await db.query('todo', where: 'id=?', whereArgs: [id]);
    if (maps.length > 0) {
      return Todo.fromMap(maps.first);
    }
    return null;
  }

  Future<int> deleteTodo(int id) async {
    final db = await _db;
    return await db.delete('todo', where: 'id=?', whereArgs: [id]);
  }

  Future<int> updateTodo(Todo todo) async {
    final db = await _db;
    return await db
        .update('todo', todo.toMap(), where: 'id=?', whereArgs: [todo.id]);
  }

  Future close() async {
    final db = await _db;
    db.close();
  }
}

【讨论】:

  • 我会调用 getInstance() 方法吗
  • 你打算在哪里上课?
  • 好的,我只是把它放在 TodoProvider 构造函数上......似乎工作正常
  • 嗯,我明白了。是的,私有构造函数和 getInstance() 应该放在 TodoProvider 类中。对不起,如果我没有说清楚:)
猜你喜欢
  • 2020-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-02
相关资源
最近更新 更多