Flutter flatter_bloc-如何在屏幕之间保持内存中的变量
我正在使用flutter_bloc处理我的flutter应用程序中的状态。我用Firestore作为存储 我的问题:Flutter flatter_bloc-如何在屏幕之间保持内存中的变量,flutter,google-cloud-firestore,bloc,Flutter,Google Cloud Firestore,Bloc,我正在使用flutter_bloc处理我的flutter应用程序中的状态。我用Firestore作为存储 我的问题: 存储并保存临时变量的最佳方法是什么 整个屏幕都可用吗 如果我想 使用我需要传递的嵌套集合构建firestore查询 文档id通过bloc和存储库来构建查询 在我的例子中,我需要存储id,以便能够使用文档中的嵌套集合构建firestore查询 我在firestore中有以下结构: school (document) - courses (collection) - co
school (document)
- courses (collection)
- course1 (document)
- course2 (document)
- ...
- sections (collection)
- ...
查询:
要获得课程:
Firestore.instance
.collection('schools')
.document('<school id>')
.collection("courses")
.snapshots();
Firestore.instance
.收藏(‘学校’)
.文件(“”)
.收藏(“课程”)
.快照();
要将各部分添加到课程中,请执行以下操作:
Firestore.instance
.collection('schools')
.document('<school id>')
.collection('courses')
.document('<course id>')
.collection('sections')
.snapshots();
Firestore.instance
.收藏(‘学校’)
.文件(“”)
.收藏(‘课程’)
.文件(“”)
.collection(“节”)
.快照();
因此,我需要以某种方式保留“学校id”和“课程id”,并将它们传递给bloc和存储库,以构建firestore查询
目前,正在加载学校的bloc函数将从firestore中加载它,然后将其序列化到共享_首选项中
读取学校的函数将从共享的_首选项中读取,而不是从firestore中读取。因此,当我需要数据时,我可以从另一个屏幕访问共享的_首选项。但不知怎么的,这感觉有点乱。我已经研究了hydrated_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();
}
}
类FirebaseCourseRepository实现CourseRepository{
final courseCollection=Firestore.instance
.收藏(‘学校’)
.document(“3kRHuyk20UggHwm4wrUI”)//这是我需要将文档id从bloc传递到的地方。
.托收(“课程”);
@凌驾
河道(){
return courseCollection.snapshots()
.map((快照){
返回快照文件
.map((doc)=>Course.fromEntity(CourseEntity.fromSnapshot(doc)))
.toList();
});
}
@凌驾
未来课程(课程){
return courseCollection.add(course.toEntity().toDocument());
}
@凌驾
未来更新课程(课程更新课程){
返回路线集合
.document(updatedCourse.id)
.updateData(updatedCourse.toEntity().toDocument());
}
@凌驾
未来删除课程(课程)异步{
返回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();
}
}
class CourseBloc扩展了Bloc{
期末课程储备(课程储备);;
流订阅(u courseSubscription);;
//存储库是通过构造函数注入的,因此它可以
//容易测试。
CourseBloc({@required CourseRepository CourseRepository})
:assert(courseRepository!=null),
_courseRepository=courseRepository;
@凌驾
get initialState=>CourseInitState();
@凌驾
Stream mapEventToState(CourseeEvent事件)异步*{
如果(事件为LoadCoursesEvent){
产量*(事件);
}else if(事件为CoursesLoadedEvent){
产量*\u地图课程加载状态(事件);
}else if(事件为AddCourseeEvent){
产量*_mapAddCourseToState(事件);
}else if(事件为UpdateCourseEvent){
产量*\u地图更新课程状态(事件);
}else if(事件为DeleteCourseEvent){
产量*(事件);
}
}
//加载所有课程
Stream _mapLoadCoursesToState(LoadCoursesEvent事件)异步*{
屈服过程加载状态();
_课程订阅?.cancel();
_courseSubscription=\u courseRepository.courses()。请听(
(课程){
派遣(
课程加载事件(课程),
);
},
);
}
Stream\u MapCourseSLoadedState(CoursesLoadedEvent事件)异步*{
收益课程加载状态(事件课程);
}
流\u mapAddCourseToState(AddCourseeEvent事件)异步*{
_courseRepository.addCourse(event.course);
}
流_MapUpdateCourseTState(UpdateCourseEvent事件)异步*{
_courseRepository.updateCourse(event.updatedCourse);
}
流\u mapDeleteCourseToState(DeleteCourseeEvent事件)异步*{
_courseRepository.deleteCurse(event.course);
}
@凌驾
无效处置(){
_课程订阅?.cancel();
super.dispose();
}
}
没有一种正确的方法可以做到这一点。但总的来说,我宁愿让存储库保持无状态。您可以做的是引入从某些存储库加载ID的父组,子组依赖于父组提供ID。请查看官方文档中的Todos示例。谢谢菲利普,这是一个有趣的建议。在谈论父集团和子集团时,您是指集团对集团的沟通吗?我已经决定为共享_首选项创建一个存储库,并将该存储库注入到我需要它们的BLOCS中。因此,我可能会有多个存储库,我会将它们注入到BLOC中。我将有一个带有getString和setString方法的SharedStoreRepository。如果在某个时候,我不想使用共享的_首选项,但使用sembast,我可以直接交换存储库。我认为这样代码就保持了解耦性和可测试性。我不知道这是否是最佳实践,但由于文档中没有这一点,我想这是我的方法。好的,它实际上是文档,我需要新的眼镜。。。Th