The non-nullable variable '_database' must be initialized
Solution 1
There are two problems in your code which both comes from the new Dart non-nullable by default (NNBD) feature introduced with version 2.12.0. Both problems can be found in the following segment:
static Database _database;
Future<Database> get database async {
if (_database == null) {
_database = await _initiateDatabase();
}
return _database;
}
First, in Dart 2.12.0, Database
means a type which does not allow null
as value. In your case, you define a variable _database
which is not being initialized with any value. So this variable is going to have the value null
. But Database
does not allow that.
Instead, we need to use the type Database?
which allows us to point to a Database
object or null
:
static Database? _database;
Future<Database> get database async {
if (_database == null) {
_database = await _initiateDatabase();
}
return _database;
}
Now we get a new problem:
A value of type 'Database?' can't be returned from the function 'database' because it has a return type of 'Future<Database>'
The reason for this is Dart null-safety feature does not promote class fields when doing if (_database == null)
. You can read more about that here and the reason why: Dart null safety doesn't work with class fields
To fix this we can rewrite your code to:
static Database? _database;
Future<Database> get database async =>
_database ??= await _initiateDatabase();
The ??=
operator will check if _database
is null
and set it to the value of await _initiateDatabase()
if that is the case and then return the new value of _database
. If _database
already has a value, it will just be returned.
A good list of null-aware operators in Dart can be found here: https://medium.com/@thinkdigitalsoftware/null-aware-operators-in-dart-53ffb8ae80bb
You can read more about Dart non-nullable by default here: https://dart.dev/null-safety
Bonus
I think you should also change:
_initiateDatabase() async {
To:
Future<Database> _initiateDatabase() async {
Since we do not not know which type _initiateDatabase
returns and Dart will therefore assume it is dynamic
which is properly not what you want.
Solution 2
Maybe this will help you, please flutter sdk change as as follows
sdk: ">=2.12.0 <3.0.0"
=> sdk: ">=2.7.0 <3.0.0"
Solution 3
import 'dart:io';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
class DatabaseHelper {
static final dbname = "myDatabase.db";
static final dbversion = 1;
static final tablename = "myTable";
static final columnId = "id";
static final columnName = "name";
DatabaseHelper._privateConstructor();
static final DatabaseHelper instance = DatabaseHelper._privateConstructor();
static Database? _database;
Future<Database?> get database async {
if (_database != null) {
return _database;
}
_database = await initiateDatabase();
return _database;
}
initiateDatabase() async {
Directory directory = await getApplicationDocumentsDirectory();
String path = join(directory.path, dbname);
return await openDatabase(path, version: dbversion, onCreate: onCreate);
}
Future onCreate(Database db, int dbversion) async {
return await db.execute('''
CREATE TABLE $tablename ($columnId INTEGER PRIMARY KEY,
$columnName TEXT NOT NULL)
''');
}
Future<int> insert(Map<String, dynamic> row) async {
Database? db = await instance.database;
return await db!.insert(tablename, row);
}
Future<List<Map<String, dynamic>>> queryAll() async {
Database? db = await instance.database;
return await db!.query(tablename);
}
Future<int> update(Map<String, dynamic> row) async {
Database? db = await instance.database;
int id = row[columnId];
return await db!
.update(tablename, row, where: '$columnId=?', whereArgs: [id]);
}
Future<int> delete(int id) async {
Database? db = await instance.database;
return await db!.delete(tablename, where: '$columnId=?', whereArgs: [id]);
}
}
sanjay .k.santhosh
Updated on July 27, 2022Comments
-
sanjay .k.santhosh almost 2 years
I am using flutter to make a Windows app and while using the sqflite and making a database, this error pops up I don't know how to really fix this.
import 'dart:io'; import 'package:path_provider/path_provider.dart'; import 'package:path/path.dart'; import 'package:sqflite/sqflite.dart'; class DatabaseHelper { static final _dbName = 'Database.db'; static final _dbVersion = 1; static final _tableName = 'my table'; static final columnId = '_id'; static final columnName = 'name'; DatabaseHelper._privateConstuctor(); static final DatabaseHelper instance = DatabaseHelper._privateConstuctor(); static Database _database; Future<Database> get database async { if (_database == null) { _database = await _initiateDatabase(); } return _database; } _initiateDatabase() async { Directory directory = await getApplicationDocumentsDirectory(); String path = join(directory.path, _dbName); return await openDatabase(path, version: _dbVersion, onCreate: _onCreate); } Future _onCreate(Database db, int version) async { await db.execute(''' CREATE TABLE $_tableName ( $columnId INTEGER PRIMARY KEY, $columnName TEXT NOT NULL) '''); } Future<int> insert(Map<String, dynamic> row) async { Database db = await instance.database; return await db.insert(_tableName, row); } Future<List<Map<String, dynamic>>> queryAll() async { Database db = await instance.database; return await db.query(_tableName); } Future<int> update(Map<String, dynamic> row) async { Database db = await instance.database; int id = row[columnId]; return await db .update(_tableName, row, where: '$columnId = ?', whereArgs: [id]); } Future<int> delete(int id) async { Database db = await instance.database; return await db.delete(_tableName, where: '$columnId = ?', whereArgs: [id]); } }
This is the code i use for the databasehelper....it shows error in _database like this:
The non-nullable variable '_database' must be initialized. Try adding an initializer expression.