Flutter Web端Sqflite CRUD操作依赖配置错误求助
Flutter SQLite CRUD 跨平台适配问题解决
问题场景
学习Flutter时创建my_diary_using_sqflite项目,练习SQLite数据库CRUD操作,在适配sqflite、sqflite_common_ffi、sqflite_common_ffi_web三个包时遇到报错。
首次报错(Chrome运行提交笔记时)
Error: Bad state: databaseFactory not initialized
databaseFactory is only initialized when using sqflite. When usingsqflite_common_ffi
You must calldatabaseFactory = databaseFactoryFfi;before using global openDatabase API
pubspec.yaml 依赖配置
dependencies: flutter: sdk: flutter cupertino_icons: ^1.0.2 sqflite: ^2.3.3 intl: ^0.19.0 path_provider: ^2.1.3 sqflite_common_ffi: ^2.3.3 sqflite_common_ffi_web: ^0.4.3+1
修改main.dart后的报错
修改main.dart初始化databaseFactoryFfi后,Web端出现白屏,报错:
Rejecting promise with error: Unsupported operation: Unsupported on the web, use sqflite_common_ffi_web
相关代码
note_repository.dart(CRUD实现)
import 'package:my_diary_using_sqflite/Models/note.dart'; import 'package:sqflite/sqflite.dart'; import 'package:path/path.dart'; class NotesRepository { static const _dbName = 'notes_database.db'; static const _tableName = 'notes'; static Future<Database> database() async { return openDatabase( join(await getDatabasesPath(), _dbName), onCreate: (db, version) { return db.execute( 'CREATE TABLE $_tableName(id INTEGER PRIMARY KEY, title TEXT, description TEXT, createdAt TEXT)'); }, version: 1, ); } static insert({required Note note}) async { print("Finally entering inserted function"); final db = await database(); await db.insert(_tableName, note.toMap()); } static Future<List<Note>> getNotes() async { final db = await database(); final List<Map<String, dynamic>> maps = await db.query(_tableName); return List.generate(maps.length, (i) { return Note( id: maps[i]['id'] as int, title: maps[i]['title'] as String, description: maps[i]['description'] as String, createdAt: DateTime.parse(maps[i]['createdAt'])); }); } }
修改后的main.dart
import 'package:flutter/material.dart'; import 'package:my_diary_using_sqflite/Screens/home_screen.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; void main() { WidgetsFlutterBinding.ensureInitialized(); sqfliteFfiInit(); databaseFactory = databaseFactoryFfi; runApp(MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, title: "My Diary", home: Home_Screen()); } }
解决方案
问题核心是未针对Web/桌面/移动端配置对应的数据库工厂,且数据库路径处理未适配Web平台,调整如下:
1. 平台差异化初始化数据库工厂
修改main.dart,根据当前运行平台选择对应的databaseFactory:
import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:my_diary_using_sqflite/Screens/home_screen.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; import 'package:sqflite_common_ffi_web/sqflite_ffi_web.dart'; void main() { WidgetsFlutterBinding.ensureInitialized(); // 根据平台选择数据库工厂 if (kIsWeb) { databaseFactory = databaseFactoryFfiWeb; } else { sqfliteFfiInit(); databaseFactory = databaseFactoryFfi; } runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, title: "My Diary", home: Home_Screen()); } }
2. 适配不同平台的数据库路径
修改NotesRepository中的数据库路径处理逻辑,Web平台无需拼接系统路径:
import 'package:flutter/foundation.dart'; import 'package:my_diary_using_sqflite/Models/note.dart'; import 'package:sqflite/sqflite.dart'; import 'package:path/path.dart'; class NotesRepository { static const _dbName = 'notes_database.db'; static const _tableName = 'notes'; static Future<Database> database() async { String dbPath; if (kIsWeb) { // Web端直接使用数据库名称 dbPath = _dbName; } else { // 移动端/桌面端拼接系统存储路径 dbPath = join(await getDatabasesPath(), _dbName); } return openDatabase( dbPath, onCreate: (db, version) { return db.execute( 'CREATE TABLE $_tableName(id INTEGER PRIMARY KEY, title TEXT, description TEXT, createdAt TEXT)'); }, version: 1, ); } static insert({required Note note}) async { print("Finally entering inserted function"); final db = await database(); await db.insert(_tableName, note.toMap()); } static Future<List<Note>> getNotes() async { final db = await database(); final List<Map<String, dynamic>> maps = await db.query(_tableName); return List.generate(maps.length, (i) { return Note( id: maps[i]['id'] as int, title: maps[i]['title'] as String, description: maps[i]['description'] as String, createdAt: DateTime.parse(maps[i]['createdAt'])); }); } }
说明
- Web平台:使用
sqflite_common_ffi_web提供的databaseFactoryFfiWeb,数据库存储在浏览器IndexedDB中,无需系统路径拼接。 - 桌面/移动端:使用
sqflite_common_ffi(桌面)或原生sqflite(移动端),通过getDatabasesPath()获取系统默认存储路径。
内容的提问来源于stack exchange,提问作者Laksh Ahir
相关产品推荐
相关产品推荐

