Flutter中sqflite代码放置位置及DatabaseServices类调用故障排查
解决你的Flutter sqflite服务类问题
看起来你在整理sqflite代码时遇到了一个常见的陷阱,咱们一步步拆解问题并修复它。
核心问题:嵌套方法无法外部访问
你当前的DatabaseServices类里,所有数据库操作方法(insertCounter、counters等)都嵌套在whatever()函数内部。这些是whatever()的局部函数,意味着它们无法从这个方法外部访问——所以当你尝试在实例上调用db.delete()(或其他方法)时,这些方法根本不属于DatabaseServices类,自然无法调用。
另外,你的whatever()方法甚至没有被调用过,就算调用了,内部的方法也对外不可见,这完全达不到你想要的“在其他文件调用增删改查”的目的。
修正方案:重构类结构
我们需要把数据库引用变成类的成员变量,把所有操作方法定义为类的成员方法,同时推荐使用单例模式来确保整个应用只有一个数据库连接实例(避免重复打开连接浪费资源)。
以下是修正后的databaseServices.dart代码:
import 'dart:async'; import 'package:path/path.dart'; import 'package:sqflite/sqflite.dart'; import 'counter.dart'; class DatabaseServices { // 单例模式:确保全局只有一个数据库服务实例 static final DatabaseServices _instance = DatabaseServices._internal(); factory DatabaseServices() => _instance; DatabaseServices._internal(); // 数据库引用,作为类的成员变量 late final Future<Database> _database; // 初始化数据库(必须在使用前调用,比如在main函数中) Future<void> init() async { _database = openDatabase( // 数据库文件路径 join(await getDatabasesPath(), 'counter_database.db'), // 首次创建数据库时执行建表语句 onCreate: (db, version) { return db.execute( "CREATE TABLE counters(id INTEGER PRIMARY KEY, name TEXT, value INTEGER)", ); }, // 数据库版本,用于升级/降级 version: 1, ); } // 插入Counter数据 Future<void> insertCounter(Counter counter) async { final Database db = await _database; await db.insert( 'counters', counter.toMap(), conflictAlgorithm: ConflictAlgorithm.replace, // 重复ID时替换旧数据 ); } // 获取所有Counter数据 Future<List<Counter>> getCounters() async { final Database db = await _database; final List<Map<String, dynamic>> maps = await db.query('counters'); // 将Map列表转换为Counter对象列表 return List.generate(maps.length, (i) { return Counter( id: maps[i]['id'], name: maps[i]['name'], value: maps[i]['value'], ); }); } // 更新Counter数据 Future<void> updateCounter(Counter counter) async { final db = await _database; await db.update( 'counters', counter.toMap(), where: "id = ?", // 用?防止SQL注入 whereArgs: [counter.id], ); } // 删除指定ID的Counter Future<void> deleteCounter(int id) async { final db = await _database; await db.delete( 'counters', where: "id = ?", whereArgs: [id], ); } }
正确使用方式
- 先初始化数据库:在
main函数中先初始化数据库服务,确保数据库连接准备好:
import 'package:flutter/material.dart'; import 'databaseServices.dart'; void main() async { // 确保Flutter绑定初始化完成 WidgetsFlutterBinding.ensureInitialized(); // 获取数据库服务实例并初始化 final dbService = DatabaseServices(); await dbService.init(); runApp(const MyApp()); }
- 在其他文件调用方法:
import 'databaseServices.dart'; import 'counter.dart'; // 获取全局唯一的数据库服务实例 final dbService = DatabaseServices(); // 示例调用 void exampleOperations() async { // 插入一条数据 await dbService.insertCounter(Counter(id: 1, name: "测试计数器", value: 0)); // 获取所有计数器 List<Counter> counters = await dbService.getCounters(); print(counters); // 更新数据 await dbService.updateCounter(Counter(id: 1, name: "更新后的计数器", value: 5)); // 删除数据 await dbService.deleteCounter(1); }
为什么用单例?
单例模式可以保证整个应用生命周期中只有一个DatabaseServices实例,避免重复打开多个数据库连接,减少资源消耗,同时确保所有操作都指向同一个数据库。
内容的提问来源于stack exchange,提问作者gustgon1212
相关产品推荐
相关产品推荐

