如何将Dart的FirebaseManager改造为支持泛型的函数?
改造FirebaseManager以支持任意类解析
我现在有个基础的FirebaseManager,只能解析返回User类的列表,想改造它支持任意类的解析,期望能这么调用:
final result = await manager.read<User>(); final result = await manager.read<Address>(); final result = await manager.read<Contacts>();当前的使用示例和代码如下:
使用示例:
Future _firebaseFirestoreTest() async { final manager = FirebaseManager(CollectionName.newAction); final result = await manager.read(); print(result); }FirebaseManager代码:
class FirebaseManager implements DataSourceRepository { final CollectionReference _collection; FirebaseManager(String collectionName) : _collection = FirebaseFirestore.instance.collection(collectionName); @override Future<List<User>> read() async { final snapshot = await _collection.get(); final data = <User>[]; for (final document in snapshot.docs) { final json = document.data() as Map<String, dynamic>; final object = User.fromJson(json); data.add(object); } return data; } }
改造方案
要实现泛型解析,核心是让FirebaseManager能统一处理不同实体类的JSON转换,分四步完成:
1. 定义通用转换接口
创建一个抽象类,约束所有需要被解析的实体类必须实现静态fromJson方法,给FirebaseManager提供统一的转换入口:
abstract class JsonConvertible<T> { static T fromJson(Map<String, dynamic> json); }
2. 改造FirebaseManager的read方法
把原方法改成泛型方法,同时约束泛型类型必须实现JsonConvertible接口,这样就能安全调用T.fromJson完成转换:
class FirebaseManager implements DataSourceRepository { final CollectionReference _collection; FirebaseManager(String collectionName) : _collection = FirebaseFirestore.instance.collection(collectionName); // 泛型read方法,支持任意实现JsonConvertible的类 Future<List<T>> read<T extends JsonConvertible<T>>() async { final snapshot = await _collection.get(); final data = <T>[]; for (final document in snapshot.docs) { final json = document.data() as Map<String, dynamic>; // 通过泛型调用统一的fromJson方法 final object = T.fromJson(json); data.add(object); } return data; } }
3. 让实体类实现转换接口
所有需要被解析的类(比如User、Address)都要实现JsonConvertible接口:
// User类示例 class User implements JsonConvertible<User> { final String id; final String name; User({required this.id, required this.name}); // 实现fromJson方法 static User fromJson(Map<String, dynamic> json) { return User( id: json['id'], name: json['name'], ); } } // Address类示例 class Address implements JsonConvertible<Address> { final String street; final String city; Address({required this.street, required this.city}); static Address fromJson(Map<String, dynamic> json) { return Address( street: json['street'], city: json['city'], ); } }
4. 按期望方式调用
现在就能用你想要的泛型调用方式读取数据了:
Future _firebaseFirestoreTest() async { final userManager = FirebaseManager(CollectionName.newAction); // 读取User列表 final users = await userManager.read<User>(); print(users); // 读取Address列表(对应另一个集合) final addressManager = FirebaseManager(CollectionName.addresses); final addresses = await addressManager.read<Address>(); print(addresses); }
额外优化:增强健壮性
如果需要更稳定的实现,可以加入异常捕获和空数据处理:
Future<List<T>> read<T extends JsonConvertible<T>>() async { try { final snapshot = await _collection.get(); return snapshot.docs.map((doc) { // 处理空数据情况 final json = doc.data() as Map<String, dynamic>? ?? {}; return T.fromJson(json); }).toList(); } catch (e) { print('Firebase读取失败: $e'); return []; } }
内容的提问来源于stack exchange,提问作者Paul Maltsev
相关产品推荐
相关产品推荐

