我有一个基本的Firebase Manager,目前它只解析并返回一个用户列表().我如何才能让它解析并返回任何类?

它需要是这样的:


  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);
}


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;
  }
}


推荐答案

遗憾的是,不可能在DART中(或至少在Fighter中)以通用的方式实现这一点.类的静态成员不是泛型函数可用的类型参数的一部分,因此无法在泛型类型上调用工厂构造函数或静态方法.实现此功能的最直接方法是将解析回调传递给函数:

Future<List<T>> read<T>(T Function(Map<String, dynamic>) parser) 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 = parser(json);
    data.add(object);
  }

  return data;
}
final result = await manager.read<User>(User.fromJson);
final result = await manager.read<Address>(Address.fromJson);
final result = await manager.read<Contacts>(Contacts.fromJson);

还有一种稍微更方便的方法,尽管它需要一些设置并且不能动态使用.不是将解析方法传递给read函数,而是保留一个具有已知解析函数的类型查找表.然后,您可以使用泛型类型作为键,直接在read函数中使用它们:

typedef T _Parser<T>(Map<String, dynamic> map);
final Map<Type, _Parser> _parsers = {
  User: User.fromJson,
  Address: Address.fromJson,
  Contacts: Contacts.fromJson,
};

class FirebaseManager implements DataSourceRepository {
  // ...
  
  @override
  Future<List<T>> read<T>() async {
    final parser = _parsers[T];
    if (parser == null) {
      throw ArgumentError('Unsupported parsable type $T');
    }
    
    final snapshot = await _collection.get();
    final data = <T>[];

    for (final document in snapshot.docs) {
      final json = document.data() as Map<String, dynamic>;
      final object = parser(json) as T;
      data.add(object);
    }

    return data;
  }
}
final result = await manager.read<User>();
final result = await manager.read<Address>();
final result = await manager.read<Contacts>();

Flutter相关问答推荐

滚动时应用栏 colored颜色 更改Flutter

为什么我的PIN字段在第一次打字时不显示数字?

'Flutter的无效常数值错误

与FTPS连接时出现Flutter FTPConnect HandshakeException错误

DART:如何判断有时可以为空的泛型类型?

如何将小部件代码移动到另一个文件以获得更好的可读性

Flutter中不使用Container是否可以做margin

如何使自动焦点位于已经有一些文本的 TextField 的第一行?

无法应用插件com.chaquo.python

reactive_flutter_BLE - 应用找到设备但无法连接(并读取 BLE 数据)

如何(部分)更新 riverpod 中的 AsyncValue?

flutter 在文本字段中更改部分文本选定 colored颜色

当项目较少时收缩列表视图

在 Flutter 中读取 Firebase 数据库数据时遇到问题

如何从 Firebase `get()` 获取 `DocumentReference`

在flutter web中重新加载页面时保留一些状态数据的有效方法是什么?

Flutter Firestore 数据库排序最近 24 小时内最喜欢的文档

Flutter:滚动一个ListWheelScrollView,无法获取选中项的状态

Navigator.push '!_debugLocked' 上的错误:不正确

解密 Modulr 安全令牌