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

Flutter Web开发:能否用Drift预存应用启动前的数据?

在Flutter Web中用Drift实现启动前预存数据的方案

可行性说明

完全可行,但要注意Flutter Web的环境限制:Web端没有原生SQLite,Drift在Web上依赖sql.js封装内存数据库或IndexedDB做持久化。要在应用启动前预存数据,核心是提前准备好初始化后的数据库文件或脚本,在应用初始化阶段加载。

实现方法(基于Drift + sql.js)

1. 提前生成预填充的数据库文件

  • 用本地SQLite工具(如DB Browser for SQLite)创建数据库,插入所需初始数据后导出为.db文件。
  • 也可以用Drift编写本地脚本生成预填充数据库(需在非Web环境运行):
    import 'package:drift/drift.dart';
    import 'package:drift/native.dart';
    import 'package:path_provider/path_provider.dart';
    import 'package:path/path.dart' as p;
    
    part 'database.g.dart';
    
    @DataClassName('Todo')
    class Todos extends Table {
      IntColumn get id => integer().autoIncrement()();
      TextColumn get title => text()();
    }
    
    @DriftDatabase(tables: [Todos])
    class MyDatabase extends _$MyDatabase {
      MyDatabase() : super(_openConnection());
    
      static LazyDatabase _openConnection() {
        return LazyDatabase(() async {
          final dbFolder = await getApplicationDocumentsDirectory();
          final file = File(p.join(dbFolder.path, 'prepopulated.db'));
          return NativeDatabase(file);
        });
      }
    
      @override
      int get schemaVersion => 1;
    }
    
    void main() async {
      final db = MyDatabase();
      // 插入预存数据
      await db.into(db.todos).insert(TodosCompanion.insert(title: '初始任务1'));
      await db.into(db.todos).insert(TodosCompanion.insert(title: '初始任务2'));
      await db.close();
      print('预填充数据库生成完成');
    }
    
    运行该脚本后,会在本地生成包含预存数据的prepopulated.db文件。

2. 在Web项目中加载预填充数据库

  • 将生成的.db文件放到Flutter Web的web目录下。
  • 修改Drift的Web数据库连接逻辑,加载预存文件:
    import 'package:drift/drift.dart';
    import 'package:drift/web.dart';
    import 'package:http/http.dart' as http;
    
    part 'database.g.dart';
    
    @DriftDatabase(tables: [Todos])
    class MyDatabase extends _$MyDatabase {
      MyDatabase() : super(_openConnection());
    
      static LazyDatabase _openConnection() {
        return LazyDatabase(() async {
          // 加载预填充的数据库文件
          final response = await http.get(Uri.parse('prepopulated.db'));
          final bytes = response.bodyBytes;
    
          // 初始化Web数据库,传入预存数据
          return WebDatabase.withStorage(
            await DriftWebStorage.indexedDb('my_app_db'),
            initialData: bytes,
          );
        });
      }
    
      @override
      int get schemaVersion => 1;
    }
    
    应用启动时会优先加载预存的数据库文件,初始化完成后即可直接使用其中的数据。

替代方案

如果不想提前生成数据库文件,可选择以下两种思路:

  • 初始化脚本抽离:在Drift数据库类的MigrationStrategy中执行批量插入,将预存数据抽成单独的常量文件,避免逻辑过度嵌入:
    @override
    MigrationStrategy get migration => MigrationStrategy(
          onCreate: (m) async {
            await m.createAll();
            // 插入预存数据
            await batch((b) {
              b.insertAll(todos, [
                Todo(title: '初始任务1'),
                Todo(title: '初始任务2'),
              ]);
            });
          },
        );
    
  • 直接操作IndexedDB:不依赖Drift,用Web原生的IndexedDB API提前写入数据,适合数据结构简单的场景,但需要处理Web异步逻辑。

关于Firebase等在线数据库

并非必须使用。在线数据库适合多端同步、实时更新的场景,而本地预存数据更适合离线可用、初始数据固定的需求,两者也可以结合使用(比如先加载本地预存数据,再同步云端最新内容)。

内容的提问来源于stack exchange,提问作者Laith Alfar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 07:43:01