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

Flutter中使用sqflite创建数据表的数据类型适配问题

解决sqflite存储电影数据的字段问题

核心问题分析

你遇到的三个字段存储失败问题,根源在Model类命名错误、SQLite不支持原生数组类型以及部分字段的序列化/反序列化逻辑缺失:

  • genre_ids是数组类型,但SQLite没有原生数组字段,直接存储List会失败
  • Model类的构造函数名与类名不匹配,导致数据解析异常
  • vote_average的类型处理不够严谨,存在潜在类型转换问题

修复步骤及代码修改

1. 修正Model类的构造函数名称与字段处理逻辑

原Model类名为Movies,但构造函数用了PopularMovies,会导致实例化时无法正确映射数据,同时补充数组和浮点类型的序列化/反序列化逻辑:

class Movies {
  int? id;
  String? title;
  String? overview;
  List<int>? genreIds;
  double? voteAverage; // 替换dynamic为double,匹配API返回的浮点类型
  String? posterPath;

  // 统一构造函数名称为Movies
  Movies({
    this.id,
    this.title,
    this.overview,
    this.genreIds,
    this.voteAverage,
    this.posterPath,
  });

  // 修正工厂构造函数名称,补充数组和浮点类型解析逻辑
  Movies.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    title = json['title'];
    overview = json['overview'];
    // 安全解析genre_ids数组
    genreIds = json['genre_ids'] != null ? List<int>.from(json['genre_ids']) : [];
    // 确保vote_average转为double类型
    voteAverage = (json['vote_average'] as num?)?.toDouble();
    posterPath = json['poster_path'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = {};
    data['id'] = id;
    data['title'] = title;
    data['overview'] = overview;
    data['vote_average'] = voteAverage;
    // 将数组转为JSON字符串,适配SQLite的TEXT字段
    data['genre_ids'] = genreIds != null ? jsonEncode(genreIds) : null;
    data['poster_path'] = posterPath;
    return data;
  }
}

2. 修改建表语句,适配数组的字符串存储

把genre_ids的字段类型改为TEXT,用来存储序列化后的JSON字符串:

// 创建数据库和Movies表
initDB() async {
  Directory documentsDirectory = await getApplicationDocumentsDirectory();
  final path = join(documentsDirectory.path, 'movies.db');

  return await openDatabase(path, version: 1, onOpen: (db) {},
      onCreate: (Database db, int version) async {
    await db.execute('CREATE TABLE Movies('
        'id INTEGER PRIMARY KEY,'
        'title TEXT,'
        'overview TEXT,'
        'vote_average REAL,'
        'poster_path TEXT,'
        'genre_ids TEXT' // 改为TEXT类型,存储JSON字符串
        ')');
  });
}

3. 读取数据时解析genre_ids字符串

从数据库读取数据时,需要把存储的JSON字符串转回List:

// 示例:从数据库读取单条电影数据
Future<Movies?> getMovie(int id) async {
  final db = await initDB();
  final maps = await db.query('Movies', where: 'id = ?', whereArgs: [id]);
  
  if (maps.isNotEmpty) {
    var movieMap = maps.first;
    // 解析genre_ids的JSON字符串为数组
    if (movieMap['genre_ids'] != null) {
      movieMap['genre_ids'] = List<int>.from(jsonDecode(movieMap['genre_ids']));
    }
    return Movies.fromJson(movieMap);
  }
  return null;
}

验证要点

  • 存储数据时必须调用toJson()将数据转为Map,确保genre_ids被序列化为JSON字符串
  • 读取数据时必须将genre_ids的字符串反序列化为List
  • vote_average统一使用double类型,避免dynamic带来的类型不确定问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 08:06:21