flutter - Flutter 从服务返回解析动态对象
问题描述
我创建了多个模型并使用 json_serialization
示例公司和员工等等。
import 'package:json_annotation/json_annotation.dart';
part 'company.g.dart';
@JsonSerializable()
class Company {
Company({this.id, this.name});
String id;
String name;
factory Company.fromJson(Map<String, dynamic> json) => _$CompanyFromJson(json);
Map<String, dynamic> toJson() => _$CompanyToJson(this);
}
import 'package:json_annotation/json_annotation.dart';
part 'employee.g.dart';
@JsonSerializable()
class Employee {
Employee({this.id, this.name, this.email, this.phone, this.photo});
String id;
String name;
String email;
String phone;
String photo;
factory Employee.fromJson(Map<String, dynamic> json) => _$EmployeeFromJson(json);
Map<String, dynamic> toJson() => _$EmployeeToJson(this);
}
现在我想创建一个可重用的服务,它可以返回带有 Company、Employee 或其他类型的 Stream。我正在使用 Firebase,所以返回类型是 Map。
示例服务类
class BaseService<T> {
final String collection;
CollectionReference _collectionRef;
FirebaseBase({@required this.collection}) {
_collectionRef = Firestore.instance.collection(collection);
}
Stream<List<T>> find() {
return inColRef.snapshots().map((list) {
return list.documents.map((doc) {
final Map<String, dynamic> data = doc.data;
data['id'] = doc.documentID;
return data;
}).toList();
});
}
}
如何将返回数据(地图)转换为 Company 或 Employee 类型。
这些类可以使用 fromJson(data) 的工厂。但我不能返回 T.fromJson(data)。
我想得到
Stream<List<Company>> companies = ServiceBase('companies').find();
Stream<List<Employee>> employees = ServiceBase('employee').find();
解决方案
这是您使用当前代码完成通用分配的方式:
class BaseService<T> {
final String collection;
CollectionReference _collectionRef;
FirebaseBase({@required this.collection}) {
_collectionRef = Firestore.instance.collection(collection);
}
Stream<List<T>> find() {
return inColRef.snapshots().map((list) {
return list.documents.map((doc) {
final Map<String, dynamic> data = doc.data;
data['id'] = doc.documentID;
return _build(data) as T;
}).toList();
});
}
dynamic _build(final Map<String, dynamic> data) {
if(collection == 'companies') {
return Company.fromJson(data);
} else if(collection == 'employee') {
return Employee.fromJson(data);
}
... throw if invalid collection passed ? ...
}
}
这将被称为:
Stream<List<Company>> companies = BaseService<Company>('companies').find();
Stream<List<Employee>> employees = BaseService<Employee>('employee').find();
我建议您使用模板方法模式使用不同的对象结构,例如:
class CompanyService extends BaseService<Company> {
CompanyService() : super('companies');
Company build(final Map<String, dynamic> data) => Company.fromJson(data);
}
class EmployeeService extends BaseService<Employee> {
EmployeeService() : super('employee');
Employee build(final Map<String, dynamic> data) => Employee.fromJson(data);
}
abstract class BaseService<T> {
final String collection;
CollectionReference _collectionRef;
BaseService(this.collection) {
_collectionRef = Firestore.instance.collection(collection);
}
T build(final Map<String, dynamic> data);
Stream<List<T>> find() {
return inColRef.snapshots().map((list) {
return list.documents.map((doc) {
final Map<String, dynamic> data = doc.data;
data['id'] = doc.documentID;
return build(data);
}).toList();
});
}
}
这将导致调用代码看起来像这样:
Stream<List<Company>> companies = CompanyService().find();
Stream<List<Employee>> employees = EmployeeService().find();