【问题标题】:The non-nullable variable '_database' must be initialized必须初始化不可为空的变量“_database”
【发布时间】:2021-07-06 23:40:54
【问题描述】:

我正在使用flutter制作一个Windows应用程序,在使用sqflite制作数据库时,弹出这个错误我不知道如何真正解决这个问题。

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]);
  }
}

这是我用于数据库助手的代码....它在 _database 中显示错误,如下所示:

The non-nullable variable '_database' must be initialized.
Try adding an initializer expression.

【问题讨论】:

  • 您的变量static Database _database; 在初始化时未分配任何值。所以值将是null。但是因为您使用的是 Dart 2.12,所以类型 Database 是不可为空的类型,因此它永远不可能是 null。如果你想让它的值为null,你应该将类型更改为Database?,这允许变量指向Database对象或null
  • 谢谢它的工作,但现在它显示“'数据库类型的值?'无法从函数“database”返回,因为它的返回类型为“Future”。
  • 这能回答你的问题吗? Non-nullable instance field must be initialized

标签: sql database flutter dart sqflite


【解决方案1】:
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]);
  }
}

【讨论】:

  • edit您的回答并解释此代码的作用,以获得更多说明。阅读How to Answer 并使用tour 了解该网站的运作方式。
【解决方案2】:

也许这会对你有所帮助, 请flutter sdk更改如下

sdk: "&gt;=2.12.0 &lt;3.0.0" => sdk: "&gt;=2.7.0 &lt;3.0.0"

【讨论】:

    【解决方案3】:

    您的代码中有两个问题都来自于 2.12.0 版引入的新的默认情况下不可为空 (NNBD) 功能的 Dart。这两个问题都可以在以下部分中找到:

      static Database _database;
      Future<Database> get database async {
        if (_database == null) {
          _database = await _initiateDatabase();
        }
        return _database;
      }
    

    首先,在 Dart 2.12.0 中,Database 表示不允许 null 作为值的类型。在您的情况下,您定义了一个变量_database,它没有被任何值初始化。所以这个变量的值是null。但是Database 不允许这样做。

    相反,我们需要使用Database? 类型,它允许我们指向Database 对象或null

      static Database? _database;
      Future<Database> get database async {
        if (_database == null) {
          _database = await _initiateDatabase();
        }
        return _database;
      }
    

    现在我们遇到了一个新问题:

    A value of type 'Database?' can't be returned from the function 'database' because it has a return type of 'Future<Database>'
    

    这样做的原因是 Dart 空安全功能在执行 if (_database == null) 时不会提升类字段。您可以在此处阅读更多相关信息以及原因:Dart null safety doesn't work with class fields

    为了解决这个问题,我们可以将您的代码重写为:

      static Database? _database;
      Future<Database> get database async =>
          _database ??= await _initiateDatabase();
    

    ??= 运算符将检查_database 是否为null,如果是,则将其设置为await _initiateDatabase() 的值,然后返回_database 的新值。如果_database 已经有值,则直接返回。

    可以在此处找到 Dart 中可识别空值的运算符的良好列表:https://medium.com/@thinkdigitalsoftware/null-aware-operators-in-dart-53ffb8ae80bb

    您可以在此处阅读有关默认情况下不可为空的 Dart 的更多信息: https://dart.dev/null-safety

    奖金

    我认为你也应该改变:

    _initiateDatabase() async {
    

    收件人:

    Future<Database> _initiateDatabase() async {
    

    由于我们不知道 _initiateDatabase 返回的类型,因此 Dart 会假设它是 dynamic,这不是你想要的。

    【讨论】:

    • 感谢您的帮助和链接,它真的很有帮助......
    • @sanjay.k.santhosh 我们还有更多的问题需要考虑吗?如果不是,请接受我的回答。 :)
    • 最佳答案,你拯救了我的一天。 +1
    • 哦,谢谢伙计:D 最佳答案
    • 谢谢你,为我节省了很多时间:)
    猜你喜欢
    • 1970-01-01
    • 2023-01-05
    • 2021-09-14
    • 1970-01-01
    • 2016-07-28
    • 2020-05-31
    • 2021-07-06
    • 1970-01-01
    • 2022-01-25
    相关资源
    最近更新 更多