You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

正确使用方式

  1. 先初始化数据库:在main函数中先初始化数据库服务,确保数据库连接准备好:
import 'package:flutter/material.dart';
import 'databaseServices.dart';

void main() async {
  // 确保Flutter绑定初始化完成
  WidgetsFlutterBinding.ensureInitialized();
  // 获取数据库服务实例并初始化
  final dbService = DatabaseServices();
  await dbService.init();
  runApp(const MyApp());
}
  1. 在其他文件调用方法:
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 00:47:47