如何将 Flutter 应用程序连接到本地数据库?

How to connect a Flutter Application with local Database?

我正在用一个小型数据库做一个简单的 flutter 应用程序,但是当我尝试向我的 table 中插入数据时,我出现了这个错误:
发生异常。

NoSuchMethodError(NoSuchMethodError:方法 'insert' 在 null 上被调用。接收者:null 尝试调用:insert("userTable", _LinkedHashMap len:3))
这是我的代码:

 // database_helper.dart

import 'dart:io';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
import 'package:sqflite/sqlite_api.dart';
import 'package:test_sql/models/user.dart';

class DataBaseHelper{
  final String tableUser = "userTable" ; 
  final String columnId = "id" ; 
  final String columnName = "username" ; 
  final String columnPassword = "password" ; 

  static final DataBaseHelper _instance = new DataBaseHelper.internal();

    DataBaseHelper.internal(); 

    factory DataBaseHelper() => _instance ; 

    static Database _db ; 

    Future<Database> get dbase async{
      if(_db !=null){
        return _db ; 
      }
      else
      {
        _db = await initDb() ; 
      }
    }    

    initDb() async {
      Directory documentDirectory = await getApplicationDocumentsDirectory() ; 
      String  path = join(documentDirectory.path,"mydb.db") ; 
      var ourDb = await openDatabase(path, version: 1,onCreate: _onCreate);
      return ourDb ; 
                }
    void _onCreate(Database db , int version) async {
      await db.execute("CREATE TABLE $tableUser($columnId INTEGER PRIMARY KEY , $columnName TEXT,$columnPassword TEXT)");
      }
    Future<int> saveUser (User user) async{
      var dbClient =  await dbase ;  
      await initDb() ; 
      int result = await dbClient.insert(tableUser, user.toMap(),); // insert(tableUser, user.toMap())
      return result ; 
    }
    Future<List> getAllUsers() async {
      var dbClient =  await dbase ; 
      var result = await dbClient.rawQuery("SELECT * FROM $tableUser") ; 
      return result.toList() ; 
    }
    Future<User> getUser(int userId) async {
      var dbClient =  await dbase ; 
      var result = await dbClient.rawQuery("SELECT * FROM $tableUser Where $columnId = $userId ") ; 
      if(result.length==0) return null ; 
      return new User.fromMap(result.first) ; 
    }
    Future<int> deleteUser(int userId) async{
    var dbClient =  await dbase ; 
    return await dbClient.delete(tableUser,where: "$columnId=?",whereArgs: [userId]) ;    
    }
    Future<int> updateUser(User user) async {
      var dbClient =  await dbase ; 
      return dbClient.update(tableUser, user.toMap(),where: "$columnId=?",whereArgs: [user.id]) ; 
    }
    Future close() async {
      var dbClient =  await dbase ; 
      return dbClient.close() ;  
    }
} 

//user.dart
class User{
  String _username ; 
  String _password ; 
  int _id ;


  User(this._id,this._username,this._password) ; 

  User.map(dynamic obj ){
    this._username = obj['username'] ; 
    this._password = obj['password'] ; 
    this._id = obj['id'] ; 
  }
  String get username => _username ; 
  String get password => _password ; 
  int get id => _id ; 

  Map<String,dynamic> toMap() {
    var map = new Map<String,dynamic>() ; 
    map["username"] = _username ; 
    map["password"] = _password ; 
    if(_id != null){
      map["id"] = _id ; 
    }
    return map ; 
  } 
  User.fromMap(Map<String,dynamic>map){
    this._username=map["username"] ; 
    this._password=map["password"] ; 
    this._id=map["id"] ; 
  }
}

 // main.dart

import 'package:flutter/material.dart';
import 'package:test_sql/database_helper.dart';
import 'package:test_sql/models/user.dart';


void main() async {
  var db = new DataBaseHelper() ; 
  int savedUserId = await db.saveUser(new User(1,"Samir Ben Halima", "Sonia el Ayeb")) ; 
  print(savedUserId)   ; 
    runApp( MaterialApp(
      title: "3atba",
      home: MyApp(),
    )
  );
}
class MyApp extends StatelessWidget {
  const MyApp({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Scaffold(
        appBar: AppBar(
          title: Text("3atba"),
          centerTitle: true,
          backgroundColor: Colors.green,
        ),
      ),
    );
  }
}

pubspec.yaml

name: test_sql
description: A new Flutter project.

# The following defines the vers[![this is the place of the ERROR][1]][1]ion and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a +.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# In Android, build-name is used as versionName while build-number used as versionCode.
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.0.0+1

environment:
  sdk: ">=2.1.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter

  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^0.1.2
  sqflite: any
  path_provider: any

dev_dependencies:
  flutter_test:
    sdk: flutter


# For information on the generic Dart part of this file, see the
# following page: https://www.dartlang.org/tools/pub/pubspec

# The following section is specific to Flutter.
flutter:

  # The following line ensures that the Material Icons font is
  # included with your application, so that you can use the icons in
  # the material Icons class.
  uses-material-design: true

  # To add assets to your application, add an assets section, like this:
  # assets:
  #  - images/a_dot_burr.jpeg
  #  - images/a_dot_ham.jpeg

  # An image asset can refer to one or more resolution-specific "variants", see
  # https://flutter.dev/assets-and-images/#resolution-aware.

  # For details regarding adding assets from package dependencies, see
  # https://flutter.dev/assets-and-images/#from-packages

  # To add custom fonts to your application, add a fonts section here,
  # in this "flutter" section. Each entry in this list should have a
  # "family" key with the font family name, and a "fonts" key with a
  # list giving the asset and other descriptors for the font. For
  # example:
  # fonts:
  #   - family: Schyler
  #     fonts:
  #       - asset: fonts/Schyler-Regular.ttf
  #       - asset: fonts/Schyler-Italic.ttf
  #         style: italic
  #   - family: Trajan Pro
  #     fonts:
  #       - asset: fonts/TrajanPro.ttf
  #       - asset: fonts/TrajanPro_Bold.ttf
  #         weight: 700
  #
  # For details regarding fonts from package dependencies,
  # see https://flutter.dev/custom-fonts/#from-packages

我认为错误在这里(这是固定代码):

if(_db !=null){
    return _db ; 
}else
{
    _db = await initDb() ;
    return _db; 
}

你只需要在初始化后return变量_db

希望对您有所帮助