vendredi 29 janvier 2021

SQFlite Flutter Database Creation

I want to separate all my tables to separate files, so they can independently handle their own creation and existence. I want to know if my design is practical.

Firstly, inside the main method, the database is instantiated. Next, I can register all my table's create methods to the DatabaseProvider before I open the database. Once I call open on the DatabaseProvider, it starts looping through its _helpers and calling each of them if, and only if, the database is getting created for the first time.

MAIN METHOD

  WidgetsFlutterBinding.ensureInitialized();

  DatabaseProvider dbProvider = DatabaseProvider();

  dbProvider.register(TodoHelper.onCreate);

  await dbProvider.open();

DATABASE PROVIDER

typedef DatabaseCreator(Database db, int version);


class DatabaseProvider {
  static DatabaseProvider _instance = DatabaseProvider._();

  Database db;
  List<DatabaseCreator> _creators;

  DatabaseProvider._() {
    _creators = List<DatabaseCreator>();
  }

  factory DatabaseProvider() {
    return _instance;
  }

  Future open() async {
    Directory directory = await getApplicationDocumentsDirectory();
    String path = directory.path + 'notes.db';

    db = await openDatabase(path, version: 1, onCreate: _createDB);
  }

  Future _createDB(Database db, int version) async {
    _creators
        .forEach((DatabaseCreator creator) async => await creator(db, version));
  }

  void register(DatabaseCreator creator) {
    _creators.add(creator);
  }

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

So now, a table would look like this, for example:

class TodoHelper implements TableHelper {
  static TodoHelper _instance = TodoHelper._();

  DatabaseProvider databaseProvider;

  static Future<void> onCreate(Database db, int version) async {
    await db.execute('''
          create table $tableTodo ( 
            $columnId integer primary key autoincrement, 
            $columnTitle text not null,
            $columnDone integer not null)
        ''');
  }

  TodoHelper._() {
    databaseProvider = DatabaseProvider();
  }

  factory TodoHelper() {
    return _instance;
  }
}

Note: Both tables and the database are singletons. The onCreate method is static because I don't want to instantiate all tables just to create the database so I just register their create functions instead. That would be a waste of resources.

Aucun commentaire:

Enregistrer un commentaire