初始化的数据库仍然返回null [Flutter,sqflite]

时间:2019-12-19 16:43:48

标签: flutter dart 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'抛出。感谢您的任何帮助,谢谢!

1 个答案:

答案 0 :(得分:0)

  

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

这是因为您尚未通过调用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]);
    });
  }
}