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

Flutter中使用Drift数据库存储List<String>的配置求助

在Drift中使用TypeConverter存储字符串列表的配置方法

1. 修改数据库表结构

先在movies.drift里新增一个TEXT类型字段(用于存储序列化后的JSON字符串),比如新增genres字段来存电影分类列表:

CREATE TABLE movie (
    id INT NOT NULL PRIMARY KEY AUTOINCREMENT,
    title TEXT,
    language TEXT,
    voteAverage TEXT,
    overView TEXT,
    releaseDate TEXT,
    movieImageUrl TEXT,
    genres TEXT -- 新增存储字符串列表的字段
);

2. 配置TypeConverter

有两种方式让Drift识别你的转换器,推荐全局注册:

方式一:全局注册转换器

在数据库类上添加@TypeConverters注解,让所有List<String>类型的字段自动使用该转换器:

import 'package:drift/drift.dart';
import 'dart:convert';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
import 'dart:io';

// 保留你的转换器,优化类型转换确保安全
class MovieTypeConverter extends TypeConverter<List<String>, String> {
  const MovieTypeConverter();

  @override
  List<String>? mapToDart(String? fromDb) {
    if (fromDb == null) return null;
    return List<String>.from(json.decode(fromDb));
  }

  @override
  String? mapToSql(List<String>? value) {
    if (value == null) return null;
    return json.encode(value);
  }
}

// 全局注册转换器
@DriftDatabase(include: {'movies.drift'})
@TypeConverters([MovieTypeConverter])
class MovieDatabase extends _$MovieDatabase {
  MovieDatabase() : super(_openConnection());

  // 修改表结构后必须升级schema版本
  @override
  int get schemaVersion => 2;

  // 处理数据库迁移,兼容旧版本数据
  @override
  MigrationStrategy get migration => MigrationStrategy(
    onCreate: (m) async {
      await m.createAll();
    },
    onUpgrade: (m, from, to) async {
      if (from < 2) {
        // 给旧表新增genres字段
        await m.addColumn(movie, movie.genres);
      }
    },
  );

  // 原有CRUD方法无需大幅修改,自动生成的实体类会包含新字段
  Future<List<MovieData>> getMovies() async {
    return await select(movie).get();
  }

  Future<int> saveMovie(MovieCompanion companion) async {
    return await into(movie).insert(companion);
  }

  Future<int> deleteAllMovies() async {
    return await delete(movie).go();
  }

  // 修正update方法,按ID精准更新
  Future<int> updateMovie(MovieCompanion companion) async {
    return await update(movie)
        .where((tbl) => tbl.id.equals(companion.id.value))
        .write(companion);
  }
}

LazyDatabase _openConnection(){
  return LazyDatabase(() async {
    final dbFolder = await getApplicationDocumentsDirectory();
    final file = File(p.join(dbFolder.path, 'movies.db'));
    return NativeDatabase(file);
  });
}

方式二:字段级单独配置(不推荐)

如果仅需单个字段使用转换器,可在自动生成的实体类扩展中指定,但全局注册更简洁高效,这里仅作说明,不展开代码。

3. 重新生成Drift代码

修改完配置后,执行命令重新生成代码:

flutter pub run build_runner build

4. 实际使用示例

现在可以直接存储和读取字符串列表:

// 存储带分类列表的电影
final db = MovieDatabase();
await db.saveMovie(MovieCompanion(
  title: const Value("星际穿越"),
  genres: const Value(["科幻", "冒险", "剧情"]),
));

// 读取数据,genres会自动转为List<String>
final movies = await db.getMovies();
for (var movie in movies) {
  print(movie.genres); // 输出: ["科幻", "冒险", "剧情"]
}

注意事项

  • 升级schema版本后必须实现migration,否则旧版本数据库会报错。
  • mapToDart中使用List<String>.from()确保类型安全,避免隐式转换问题。
  • 确保导入dart:convert用于JSON编解码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 15:07:32