Skip to content

Instantly share code, notes, and snippets.

@madebycm
Created April 24, 2020 09:00
Show Gist options
  • Save madebycm/67c2dd65435c009534600a6dba2f9a00 to your computer and use it in GitHub Desktop.
Save madebycm/67c2dd65435c009534600a6dba2f9a00 to your computer and use it in GitHub Desktop.
Flutter singleton DatabaseHelper
import 'dart:io';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path_provider/path_provider.dart';
class DatabaseHelper {
static final _databaseName = "MyDatabase.db";
static final _databaseVersion = 1;
static final table = 'my_table';
static final columnId = '_id';
static final columnName = 'name';
static final columnAge = 'age';
// make this a singleton class
DatabaseHelper._privateConstructor();
static final DatabaseHelper instance = DatabaseHelper._privateConstructor();
// only have a single app-wide reference to the database
static Database _database;
Future<Database> get database async {
if (_database != null) return _database;
// lazily instantiate the db the first time it is accessed
_database = await _initDatabase();
return _database;
}
// this opens the database (and creates it if it doesn't exist)
_initDatabase() async {
Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, _databaseName);
return await openDatabase(path,
version: _databaseVersion,
onCreate: _onCreate);
}
// SQL code to create the database table
Future _onCreate(Database db, int version) async {
await db.execute('''
CREATE TABLE $table (
$columnId INTEGER PRIMARY KEY,
$columnName TEXT NOT NULL,
$columnAge INTEGER NOT NULL
)
''');
}
// Helper methods
// Inserts a row in the database where each key in the Map is a column name
// and the value is the column value. The return value is the id of the
// inserted row.
Future<int> insert(Map<String, dynamic> row) async {
Database db = await instance.database;
return await db.insert(table, row);
}
// All of the rows are returned as a list of maps, where each map is
// a key-value list of columns.
Future<List<Map<String, dynamic>>> queryAllRows() async {
Database db = await instance.database;
return await db.query(table);
}
// All of the methods (insert, query, update, delete) can also be done using
// raw SQL commands. This method uses a raw query to give the row count.
Future<int> queryRowCount() async {
Database db = await instance.database;
return Sqflite.firstIntValue(await db.rawQuery('SELECT COUNT(*) FROM $table'));
}
// We are assuming here that the id column in the map is set. The other
// column values will be used to update the row.
Future<int> update(Map<String, dynamic> row) async {
Database db = await instance.database;
int id = row[columnId];
return await db.update(table, row, where: '$columnId = ?', whereArgs: [id]);
}
// Deletes the row specified by the id. The number of affected rows is
// returned. This should be 1 as long as the row exists.
Future<int> delete(int id) async {
Database db = await instance.database;
return await db.delete(table, where: '$columnId = ?', whereArgs: [id]);
}
}
@mlazzarotto
Copy link

Why when I use your code, Android Studio says "The non-nullable variable '_database' must be initialized"?
I believe you should make the database nullable.

@biniama
Copy link

biniama commented Oct 2, 2021

Hi, I also get "Non-nullable instance field '_database' must be initialized. (Documentation)" error. Did you find a fix for this? Thanks.

@jrihan
Copy link

jrihan commented Oct 23, 2021

@mlazzarotto Me too!

@joosangkim
Copy link

@biniama https://stackoverflow.com/questions/67049107/the-non-nullable-variable-database-must-be-initialized julemand101's answer is really helpful for me about new flutter null safety.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment