我正在使用flutter_bloc在Flutter App中处理状态。我正在使用Firestore作为存储。
我的问题:
就我而言,我需要存储ID,以便能够使用文档中的嵌套集合来构建Firestore查询。
我在Firestore中具有以下结构:
school (document)
- courses (collection)
- course1 (document)
- course2 (document)
- ...
- sections (collection)
- ...
查询:
要获取课程:
Firestore.instance
.collection('schools')
.document('<school id>')
.collection("courses")
.snapshots();
要获取课程的各个部分:
Firestore.instance
.collection('schools')
.document('<school id>')
.collection('courses')
.document('<course id>')
.collection('sections')
.snapshots();
因此,我需要以某种方式保留“学校ID”和“课程ID”,并将它们传递到集团和存储库中,以构建Firestore查询。
目前,我正在加载学校的bloc函数将从Firestore加载它,然后将其序列化到shared_preferences中。
读取学校的函数将从shared_preferences中读取学校,而不是从那以后的firestore。因此,当我需要数据时,可以从另一个屏幕访问shared_preferences。但是,这有点让人感到混乱。我看过hydred_bloc,它的基本作用相同,因此我可能会用它,但必须通过bloc和存储库传递变量以构建查询仍然感到混乱。
在使用bloc创建良好的体系结构方面,我是一个初学者,我希望从一开始就构建适当的东西。
有人知道更好的方法吗?
这是我的存储库类。如您所见,我需要将学校文档ID解析到Firebase存储库。目前,它已经过硬编码。
class FirebaseCourseRepository implements CourseRepository {
final courseCollection = Firestore.instance
.collection('school')
.document("3kRHuyk20UggHwm4wrUI") // this is where I need to pass the doc id from the bloc to.
.collection("course");
@override
Stream<List<Course>> courses() {
return courseCollection.snapshots()
.map((snapshot) {
return snapshot.documents
.map((doc) => Course.fromEntity(CourseEntity.fromSnapshot(doc)))
.toList();
});
}
@override
Future<void> addCourse(Course course) {
return courseCollection.add(course.toEntity().toDocument());
}
@override
Future<void> updateCourse(Course updatedCourse) {
return courseCollection
.document(updatedCourse.id)
.updateData(updatedCourse.toEntity().toDocument());
}
@override
Future<void> deleteCourse(Course course) async {
return courseCollection.document(course.id).delete();
}
}
这里是集团。我真的不知道,我如何只能将文档ID传递到存储库一次。
class CourseBloc extends Bloc<CourseEvent, CourseState> {
final CourseRepository _courseRepository;
StreamSubscription _courseSubscription;
// Repository is injected through constructor, so that it can
// be easily tested.
CourseBloc({@required CourseRepository courseRepository})
: assert(courseRepository != null),
_courseRepository = courseRepository;
@override
get initialState => CourseInitState();
@override
Stream<CourseState> mapEventToState(CourseEvent event) async* {
if(event is LoadCoursesEvent) {
yield* _mapLoadCoursesToState(event);
} else if(event is CoursesLoadedEvent) {
yield* _mapCoursesLoadedToState(event);
} else if(event is AddCourseEvent) {
yield* _mapAddCourseToState(event);
} else if(event is UpdateCourseEvent) {
yield* _mapUpdateCourseToState(event);
} else if(event is DeleteCourseEvent) {
yield* _mapDeleteCourseToState(event);
}
}
// Load all courses
Stream<CourseState> _mapLoadCoursesToState(LoadCoursesEvent event) async* {
yield CoursesLoadingState();
_courseSubscription?.cancel();
_courseSubscription = _courseRepository.courses().listen(
(courses) {
dispatch(
CoursesLoadedEvent(courses),
);
},
);
}
Stream<CourseState> _mapCoursesLoadedToState(CoursesLoadedEvent event) async* {
yield CoursesLoadedState(event.courses);
}
Stream<CourseState> _mapAddCourseToState(AddCourseEvent event) async* {
_courseRepository.addCourse(event.course);
}
Stream<CourseState> _mapUpdateCourseToState(UpdateCourseEvent event) async* {
_courseRepository.updateCourse(event.updatedCourse);
}
Stream<CourseState> _mapDeleteCourseToState(DeleteCourseEvent event) async* {
_courseRepository.deleteCourse(event.course);
}
@override
void dispose() {
_courseSubscription?.cancel();
super.dispose();
}
}