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.
Nullable variables may either contain a valid value or they may not — in the latter case they are considered to be nil . Non-nullable variables must always contain a value and cannot be nil . In Oxygene (as in C# and Java), the default nullability of a variable is determined by its type.
With null safety, all the runtime null-dereference errors will now be shown in compile time. String name = null ; // This means the variable name has a null value. Example : Dart.
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.
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"
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]);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With