Flutter SQFlite开发中factory、Future<List<Trail>>含义及空安全适配咨询
概念讲解与空安全适配方案
核心概念说明
1. factory构造方法
factory是Dart的特殊构造器关键字,调用时不会强制生成新的类实例,适合缓存复用、序列化/反序列化场景。你当前使用的Trail.fromJson就是典型的反序列化工厂方法,作用是将数据库返回的Map结构转换为Trail实体类对象。
2. Future<List> 类型含义
Future是Dart异步编程的核心类型,代表一个未来会返回结果的异步操作,数据库读写属于IO操作,天然是异步的,所以返回值必须用Future包裹。<List<Trail>>是泛型约束,代表该异步操作完成后,返回的结果是一个元素类型为Trail的列表。
3. "List is not a type"报错原因
空安全规范下要求所有集合类型必须明确指定泛型参数,不能使用无泛型的裸List声明,补全泛型即可解决该报错。
空安全适配代码修改
1. 工厂构造方法适配
空安全下直接读取json字段会因为可能为null触发编译错误,可通过默认值兜底的方式兼容:
factory Trail.fromJson(Map<String,dynamic> json){ return Trail( // 用??运算符为可能为空的字段设置兜底默认值 name: json['name'] as String? ?? '未命名路线', difficulty: json['difficulty'] as String? ?? '未知难度', distance: json['distance'] as int? ?? 0, ); }
如果你的Trail类属性允许为空,也可以将属性声明为String?、int?的可空类型,直接赋值即可。
2. FutureBuilder部分适配
空安全下即使通过snapshot.hasData判断有值,snapshot.data仍会被识别为可空类型,可通过非空断言!(此时已确认有值,断言是安全的)处理:
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), body: FutureBuilder<List<Trail>>( future: dbService.getTrails(), builder: (context, snapshot) { // 新增错误处理逻辑,避免数据库异常导致白屏 if (snapshot.hasError) { return Center(child: Text('加载失败:${snapshot.error}')); } if (!snapshot.hasData) { return const Center(child: CircularProgressIndicator()); } // 非空断言后赋值给局部变量,后续使用无需重复处理 final trailList = snapshot.data!; return ListView.builder( itemCount: trailList.length, itemBuilder: (context, index){ final trail = trailList[index]; return ListTile( title: Text(trail.name), leading: Text(trail.difficulty), trailing: Text(trail.distance.toString()), ); } ); } ) ); }
3. 数据库查询方法适配
需要为List明确指定泛型参数,同时对数据库实例、查询结果做空判断:
Future<List<Trail>> getTrails() async { await initDatabase(); // 明确指定Map的泛型,解决List无类型的报错 final List<Map<String, dynamic>>? list = await _db?.rawQuery('SELECT * FROM Trails'); // 查询结果为空时返回空列表,避免空异常 if (list == null || list.isEmpty) return []; return list.map((trail) => Trail.fromJson(trail)).toList(); }
内容的提问来源于stack exchange,提问作者Bhikkhu Subhuti
相关产品推荐
相关产品推荐

