Как совместить два потока, где второй зависит от первого?
Я создаю приложение, в котором
Document
имеет, который принадлежит.
Я работаю над основными операциями CRUD для приложения, и мне нужен метод, в котором я получаю поток, но мне также нужно смотреть его.
Проблема в том, что я понятия не имею, как вложить два потока, чтобы при обновлении
DocumentTemplate
будет обновленный
DocumentFamily
.
Я был бы очень признателен, если бы кто-нибудь показал мне, как это сделать. Я использую Flutter с ObjectBox в качестве локальной базы данных.
Вот метод, который я начал реализовывать (незавершенный):
@override
Stream<Either<DocumentTemplateFailure, DocumentTemplate>>
watchDocumentTemplateById(UniqueId templateId) {
return _box
.query(DocumentTemplateEntity_.id.equals(templateId.getOrCrash()))
.watch(triggerImmediately: true)
.map((query) {
final templateEntity = query.findFirst();
if (null != templateEntity) {
final familyOrFailureStream =
_documentFamilyRepository.watchDocumentFamilyById(
UniqueId.fromUniqueString(templateEntity.familyId));
familyOrFailureStream.listen((familyOrFailure) {
return familyOrFailure.fold(
(failure) =>
DocumentTemplateFailure.familyFailure(familyFailure: failure),
(family) => templateEntity.toDomain(family: family),
);
});
}
return left(const DocumentTemplateFailure.notFound());
});
}
И упомянутые выше классы (DocumentTemplate, DocumentTemplateEntity, DocumentFamily и DocumentFamilyEntity):
DocumentTemplate:
@freezed
class DocumentTemplate with _$DocumentTemplate {
factory DocumentTemplate({
required UniqueId id,
required DocumentTemplateTitle title,
required double leftMargin,
required double topMargin,
required double rightMargin,
required double bottomMargin,
required DocumentFamily family,
}) = _DocumentTemplate;
}
DocumentTemplateEntity:
@Entity()
class DocumentTemplateEntity {
@Id()
int obid = 0;
@Unique()
String id;
String title;
double leftMargin;
double topMargin;
double rightMargin;
double bottomMargin;
String familyId;
DocumentTemplateEntity({
required this.id,
required this.title,
required this.leftMargin,
required this.topMargin,
required this.rightMargin,
required this.bottomMargin,
required this.familyId,
});
DocumentTemplate toDomain({
required DocumentFamily family,
}) =>
DocumentTemplate(
id: UniqueId.fromUniqueString(id),
title: DocumentTemplateTitle(title),
leftMargin: leftMargin,
topMargin: topMargin,
rightMargin: rightMargin,
bottomMargin: bottomMargin,
family: family,
);
factory DocumentTemplateEntity.fromDomain(DocumentTemplate template) =>
DocumentTemplateEntity(
id: template.id.getOrCrash(),
title: template.title.getOrCrash(),
leftMargin: template.leftMargin,
topMargin: template.topMargin,
rightMargin: template.rightMargin,
bottomMargin: template.bottomMargin,
familyId: template.family.id.getOrCrash(),
);
}
DocumentFamily:
@freezed
class DocumentFamily with _$DocumentFamily {
factory DocumentFamily({
required UniqueId id,
required int position,
required String name,
}) = _DocumentFamily;
}
DocumentFamilyEntity:
@Entity()
class DocumentFamilyEntity {
@Id()
int obid = 0;
@Unique()
String id;
String name;
int position;
DocumentFamilyEntity({
required this.id,
required this.name,
required this.position,
});
DocumentFamily toDomain() => DocumentFamily(
id: UniqueId.fromUniqueString(id),
name: name,
position: position,
);
factory DocumentFamilyEntity.fromDomain(DocumentFamily family) =>
DocumentFamilyEntity(
id: family.id.getOrCrash(),
name: family.name,
position: family.position,
);
}
Заранее спасибо !
РЕДАКТИРОВАТЬ :
Я попытался решить это самостоятельно и нашел
switchMap
, который, кажется, объединяет два потока в один, но я не совсем уверен, будет ли он работать, вот обновленный
watchDocumentTemplateById
метод:
ref.: Как вложить потоки в Dart (сопоставить потоки с событиями Stream)?
@override
Stream<Either<DocumentTemplateFailure, DocumentTemplate>>
watchDocumentTemplateById(UniqueId templateId) {
return _box
.query(DocumentTemplateEntity_.id.equals(templateId.getOrCrash()))
.watch(triggerImmediately: true)
.switchMap((query) {
final templateEntity = query.findFirst();
// if(null == templateEntity) return ??? DocumentTemplateFailure.notFound();
final familyId = UniqueId.fromUniqueString(templateEntity!.familyId);
return _documentFamilyRepository.watchDocumentFamilyById(familyId).map(
(failureOrFamily) => failureOrFamily.fold(
(failure) => left(
DocumentTemplateFailure.familyFailure(familyFailure: failure),
),
(family) => right(
templateEntity.toDomain(family: family),
),
),
);
});
}
1 ответ
Рассматривали ли вы возможность использования @Entity непосредственно на
DocumentFamily
и
DocumentTemplate
классы? См. этот пример , который показывает его с пакетом
freezed
.
В любом случае вам, вероятно, потребуется представить связь между объектами как отношение ObjectBox , а не просто поле идентификатора.
Затем box.query().link() для создания запроса между сущностями. И если вы
watch()
тот, он срабатывает при изменениях в базовой сущности, а также во всех связанных.