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
相关产品推荐
相关产品推荐

