初始化数据库仍然 returns 为 null [Flutter, sqflite]

Initialized database still returns as null [Flutter, sqflite]

我正在尝试使用 sqflite 库在 Flutter 上执行 CRUD 操作。在线资源指向了一堆解决这个问题的方法。这是我的实现:

class SqlManager { 
 static const String tname = 'table1';
 static const String dname = 'database.db';
 Future<Database> db;

 initDB() async {
   Directory path = await getApplicationDocumentsDirectory();
   db = openDatabase(join(path.path, dname), version: 1, onCreate: (db, version) {
     return db.execute(
         'CREATE TABLE $tname (id INTEGER PRIMARY KEY, name TEXT, type TEXT, time1 INTEGER, time2 INTEGER, imp INTEGER, urg INTEGER)');
   });
 }

 Future<void> writing(Task task) async {
   print("called");
   final Database DB = await db;
   await DB.insert(
     tname,
     task.toMap(),
     conflictAlgorithm: ConflictAlgorithm.replace,
   );
   print("Execution completed");
 }

 Future<List<Task>> reading() async {
   Database DB = await db;
   List<Map<String, dynamic>> maps = await DB.query(tname);
   return List.generate(maps.length, (i) {
     return Task.fromMap(maps[i]);
   });
 }
} 

每当我尝试调用这些函数中的任何一个时,我都会遇到一个 NoSuchMethodError,由其中一个函数中的变量 'DB' 抛出。感谢任何帮助,谢谢!

Whenever I attempt to call any of these functions, I hit upon a NoSuchMethodError, thrown by the variable 'DB' inside one of these functions. Any help is appreciated, thanks!

这是因为您还没有通过调用 initDB() 来初始化您的数据库。因此,在调用使用数据库的方法之前先调用它。但是您最终会为每次调用重新创建每个实例。

更好的方法是为您的数据库创建单例。将您的 SqlManager 修改为如下内容:

class SqlManager { 
  static const String tname = 'table1';
  static const String dname = 'database.db';
  // Future<Database> db;

  // Make a singleton class
  SqlManager._privateConstructor();

  static final SqlManager instance = SqlManager._privateConstructor();

  // Use a single reference to the db.
  static Database _db;

  // Use this getter to use the database.
  Future<Database> get database async {
    if (_db != null) return _database;
    // Instantiate db the first time it is accessed
    _db = await _initDB();
    return _db;
  }

  // Init the database for the first time.
  _initDB() async {
    Directory path = await getApplicationDocumentsDirectory();
    return await openDatabase(join(path.path, dname), version: 1, onCreate: (db, version) {
     return db.execute(
         'CREATE TABLE $tname (id INTEGER PRIMARY KEY, name TEXT, type TEXT, time1 INTEGER, time2 INTEGER, imp INTEGER, urg INTEGER)');
    });
  }

  // Then you can use the database getter in another method
  Future<List<Task>> reading() async {
    Database DB = await instance.database;
    List<Map<String, dynamic>> maps = await DB.query(tname);
    return List.generate(maps.length, (i) {
     return Task.fromMap(maps[i]);
    });
  }
}