Flutter中导入现有SQLite数据库并初始化连接失败求助
Flutter新手数据库调用报错问题
我是Flutter新手,已将sms.db放在assets/db目录并在pubspec.yaml配置了资源路径,尝试把数据库复制到应用目录后,在categoriesList.dart调用SmsDataBaseHelper.instance.getAllCategories()时出现错误。
pubspec.yaml配置
assets: - assets/db/sms.db
database_helper.dart代码
import 'package:flutter/services.dart'; import 'package:sqflite/sqflite.dart'; import 'package:path/path.dart' as path; import 'package:path_provider/path_provider.dart'; import 'dart:io' as io; import '/models/categories.dart'; class SmsDataBaseHelper { static final SmsDataBaseHelper instance = SmsDataBaseHelper._(); static Database? _db; SmsDataBaseHelper._(); Future<Database> get db async { _db ??= await _init(); return _db!; } Future<Database> _init() async { io.Directory applicationDirectory = await getApplicationDocumentsDirectory(); String dbPathSms = path.join(applicationDirectory.path, "sms.db"); bool dbExistsSms = await io.File(dbPathSms).exists(); if (!dbExistsSms) { // Copy from asset ByteData data = await rootBundle.load(path.join("assets", "db", "sms.db")); List<int> bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes); // Write and flush the bytes written await io.File(dbPathSms).writeAsBytes(bytes, flush: true); } return await openDatabase(dbPathSms); } /// get all the words from categories Future<List<Categories>> getAllCategories() async { if (_db == null) { throw "_db is not initiated, initiate using [init(db)] function"; } List<Map>? categories; await _db!.transaction((txn) async { categories = await txn.query( "categories", columns: [ "name", "ru", ], ); }); return categories!.map((e) => Categories.fromJson(e as Map<String, dynamic>)).toList(); } }
categoriesList.dart代码
import 'package:flutter/material.dart'; import 'package:sqflite/sqflite.dart'; import '../utils/database_helper.dart'; import '../models/categories.dart'; class CategoriesList extends StatefulWidget { const CategoriesList({super.key}); @override State<CategoriesList> createState() => _CategoriesListState(); } class _CategoriesListState extends State<CategoriesList> { //late List<Categories> categoriesList; @override void initState(){ super.initState(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('SMS Home Page'), ), body: FutureBuilder<List<Categories>>( future: SmsDataBaseHelper.instance.getAllCategories(), builder: (BuildContext context, AsyncSnapshot<List<Categories>> snapshot) { switch (snapshot.connectionState) { case ConnectionState.none: return const Text('start widget'); case ConnectionState.active: case ConnectionState.waiting: return const Text('Awaiting result from api...'); case ConnectionState.done: if (snapshot.hasError) return Text('Error: ${snapshot.error}'); return Text('Result: ${snapshot.data}'); } }, ), ); } }
错误信息
调用后抛出错误:_db is not initiated, initiate using [init(db)] function
问题原因及解决办法
问题出在getAllCategories方法直接判断_db == null,但_db是通过异步getterdb初始化的,调用getAllCategories时可能还未完成初始化。
修改getAllCategories方法如下:
Future<List<Categories>> getAllCategories() async { // 先确保数据库初始化完成 final database = await db; List<Map> categories = await database.transaction((txn) async { return await txn.query( "categories", columns: [ "name", "ru", ], ); }); return categories.map((e) => Categories.fromJson(e as Map<String, dynamic>)).toList(); }
修改说明:
- 用
await db替代直接判断_db,确保数据库实例初始化完成后再执行查询 - 直接接收事务的返回值,避免原代码中可空变量强制解包的风险
内容的提问来源于stack exchange,提问作者Yaroslav
相关产品推荐
相关产品推荐

