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

如何创建Floor数据库单例对象并在多文件中复用?

实现Floor数据库的单例复用

问题描述

我正在为我的应用创建数据库,使用的是Floor数据库。已创建了如下的Entity、Dao和Database类:

@entity
class User{
  @primaryKey
  final int id;

  final String name;
  final String email;
  User(this.id, this.name, this.email);
}

@dao
abstract class UserDao {
  @Query('SELECT * FROM User')
  Future<List<User>> findAllUsers();

  @Query('DELETE FROM User WHERE id = :id')
  Future<void> deleteUserById(int id);

  @insert
  Future<void> insertUser(User user);
}

@Database(version: 1, entities: [User])
abstract class Appdatabase extends FloorDatabase{
  UserDao get userDao;
}

我在main.dart文件中通过以下代码创建了数据库实例:

final database = await $FloorAppdatabase.databaseBuilder("MY_DATABASE").build();

可以通过database.userDao().insertUser(user);存储数据,但想要在其他文件中使用该数据库对象,需要将其设置为可复用的单例,该如何实现?

解决方案

方法一:静态类实现线程安全单例

创建专门的数据库管理类,通过双重检查锁确保全局唯一实例:

import 'package:floor/floor.dart';
import 'dart:async';
// 导入你的数据库类和自动生成的代码
import 'app_database.dart';
import 'database.g.dart';

class DatabaseManager {
  static Appdatabase? _instance;
  static final _lock = Lock();

  // 私有构造函数,禁止外部实例化
  DatabaseManager._();

  static Future<Appdatabase> getInstance() async {
    if (_instance == null) {
      await _lock.synchronized(() async {
        if (_instance == null) {
          _instance = await $FloorAppdatabase.databaseBuilder("MY_DATABASE").build();
        }
      });
    }
    return _instance!;
  }
}

使用方式:在任意文件中调用获取实例后使用DAO方法

final db = await DatabaseManager.getInstance();
await db.userDao.insertUser(User(1, "张三", "zhangsan@example.com"));

方法二:全局变量快速实现(适合小型项目)

通过全局变量直接复用初始化后的实例:

  1. 在单独文件(如globals.dart)定义全局变量:
import 'app_database.dart';

late Appdatabase globalDatabase;
  1. 在main.dart中完成初始化:
void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  globalDatabase = await $FloorAppdatabase.databaseBuilder("MY_DATABASE").build();
  runApp(MyApp());
}
  1. 在其他文件直接调用:
await globalDatabase.userDao.insertUser(User(2, "李四", "lisi@example.com"));

注意:这种方式不利于代码解耦和测试,仅适合小型项目快速落地。

方法三:依赖注入管理(推荐中大型项目)

使用依赖注入框架(如get_it)管理单例,提升代码灵活性:

  1. 添加依赖到pubspec.yaml:
dependencies:
  get_it: ^7.6.0
  1. 创建依赖注入初始化文件(如locator.dart):
import 'package:get_it/get_it.dart';
import 'app_database.dart';
import 'database.g.dart';

final getIt = GetIt.instance;

Future<void> setupLocator() async {
  getIt.registerSingletonAsync<Appdatabase>(() async {
    return await $FloorAppdatabase.databaseBuilder("MY_DATABASE").build();
  });
}
  1. 在main.dart中初始化:
void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await setupLocator();
  runApp(MyApp());
}
  1. 在其他文件获取实例:
final db = await getIt.getAsync<Appdatabase>();
await db.userDao.findAllUsers();

内容的提问来源于stack exchange,提问作者sridhar venkatesan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 04:42:39