I have a basic FirebaseManager, currently it parses and returns only a list of User(). How can I make it parse and return any class?
It needs to be something like this:
final result = await manager.read<User>();
final result = await manager.read<Address>();
final result = await manager.read<Contacts>();
Usage of current manager.
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;
}
}
2
Answers
You can achieve this with generics. Check out the documentation here:
https://dart.dev/language/generics
For your example, you can include a type
T
when calling theread
function, so it’ll know to return this type (if no type is passed, it will just use and returndynamic
, which would fail in thefromJson
I guess).Which you would indeed call like this:
Update
My first thought given your update: since
isJson
isn’t defined for a generic typeT
, perhaps you can define a shared supertype for all of your serializable classes? The problem is thatfromJson
is a static method, and these are not inherited by subclasses…So I’m not sure how I’d get this to work. Let’s hope someone more knowledgeable on the topic comes around and can help us to figure this out.
Update #2
Looking at this other SO post, it’s not possible to call a static method on a generic type in Dart: Calling a static method from a generic constraint Dart
Sadly, it’s not possible to do this in Dart (or at least in Flutter) in a generic way. Static members of a class are not part of the type parameter available to generic functions, so there’s no way of calling a factory constructor or static method on a generic type. The most straightforward way of achieving this functionality is to pass a parsing callback to the function:
There is a slightly more convenient way, although it requires some setup and can’t be used dynamically. Instead of passing the parsing methods to the
read
function, keep a lookup table of types with known parsing functions. You can then use them in theread
function directly using the generic type as the key: