У меня есть веб-приложение Flutter, использующее пакет flutter_blo c с бэкэндом Firestore. Я использовал «Fluter Blo c Firebase Todo's App» в качестве отправной точки и реализовал большую часть того, что нужно.
Я могу просмотреть список проектов, добавить проект, удалить проект и обновить проект, но не могу получить пользовательский интерфейс, чтобы немедленно отразить эти изменения. Мне нужно обновить страницу sh или go на другом экране, чтобы увидеть изменения. Любая помощь приветствуется.
Проект Blo c
class ProjectsBloc extends Bloc<ProjectEvent, ProjectsState> {
final ProjectRepository _projectsRepository;
StreamSubscription _projectsSubscription;
ProjectsBloc({@required ProjectRepository projectsRepository})
: assert(projectsRepository != null),
_projectsRepository = projectsRepository;
@override
ProjectsState get initialState => ProjectsLoading();
@override
Stream<ProjectsState> mapEventToState(ProjectEvent event) async* {
if (event is LoadProjects) {
yield* _mapLoadProjectsToState(event);
} else if (event is AddProject) {
yield* _mapAddProjectToState(event);
} else if (event is UpdateProject) {
yield* _mapUpdateProjectToState(event);
} else if (event is DeleteProject) {
yield* _mapDeleteProjectToState(event);
} else if (event is ProjectsUpdated) {
yield* _mapProjectsUpdateToState(event);
}
}
Stream<ProjectsState> _mapLoadProjectsToState(LoadProjects event) async* {
_projectsSubscription?.cancel();
_projectsSubscription = _projectsRepository.projects(event.company).listen(
(projects) => add(ProjectsUpdated(projects)),
);
}
Stream<ProjectsState> _mapAddProjectToState(AddProject event) async* {
_projectsRepository.addNewProject(event.project, event.company);
}
Stream<ProjectsState> _mapUpdateProjectToState(UpdateProject event) async* {
_projectsRepository.updateProject(event.updatedProject, event.company);
}
Stream<ProjectsState> _mapDeleteProjectToState(DeleteProject event) async* {
_projectsRepository.deleteProject(event.project, event.company);
}
Stream<ProjectsState> _mapProjectsUpdateToState(ProjectsUpdated event) async* {
yield ProjectsLoaded(event.projects);
}
@override
Future<void> close() {
_projectsSubscription?.cancel();
return super.close();
}
}
Экран проекта
class ProjectsScreen extends StatefulWidget {
final User user;
ProjectsScreen({
Key key,
@required this.user,
}) : super(key: key);
@override
_ProjectsScreenState createState() => _ProjectsScreenState();
}
class _ProjectsScreenState extends State<ProjectsScreen> {
User get _user => widget.user;
//ProjectsBloc _projectsBloc;
//Project _currentProject;
@override
Widget build(BuildContext context) {
return BlocProvider<ProjectsBloc>(
create: (context) {
return ProjectsBloc(
projectsRepository: FirebaseProjectRepository(),
)..add(LoadProjects(_user.company));
},
child: Container(
child: MultiBlocProvider(
providers: [
BlocProvider<CurrentProjectBloc>(
create: (context) => CurrentProjectBloc(),
),
BlocProvider<TabBloc>(
create: (context) => TabBloc(),
),
BlocProvider<FilteredProjectsBloc>(
create: (context) => FilteredProjectsBloc(
user: _user,
projectsBloc: BlocProvider.of<ProjectsBloc>(context),
))
],
child: BlocBuilder<ProjectsBloc,ProjectsState>(
builder: (context, state) {
return Row(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width * .93,
height: double.infinity,
child: Scaffold(
appBar: AppBar(
title: Text('${_user.company} Projects'),
actions: [
FilterButton(
visible: true,
user: _user),
],
),
body:
Row(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width * .25,
height: double.infinity,
child: FilteredProject(
user: _user,
),
),
Container(
width: MediaQuery.of(context).size.width * .68,
height: double.infinity,
child: ProjectBody()),
],
),
floatingActionButton: FloatingActionButton(
onPressed: (){
Navigator.of(context).push(
MaterialPageRoute(builder: (context) {
return BlocProvider<ProjectsBloc>(
create: (context) => ProjectsBloc(
projectsRepository: FirebaseProjectRepository(),
), child: AddEditScreen(isEditing: false, user: _user,));
}),
);
} ,
child: Icon(Icons.add),
tooltip: "Add A New Project",
) ,
),
),
],
);
}),
),
),
);
}
@override
void dispose() {
super.dispose();
}
}
Виджет отфильтрованных проектов
class FilteredProject extends StatefulWidget {
final User user;
FilteredProject({
Key key,
@required this.user,
}) : super(key: key);
@override
_FilteredProjectState createState() => _FilteredProjectState();
}
class _FilteredProjectState extends State<FilteredProject> {
User get _user => widget.user;
@override
Widget build(BuildContext context) {
return BlocBuilder<FilteredProjectsBloc, FilteredProjectState>(
builder: (context, state) {
if (state is FilteredProjectLoading) {
return LoadingIndicator();
} else if (state is FilteredProjectLoaded) {
final projects = state.filteredProject;
return ListView.builder(
itemCount: projects.length,
itemBuilder: (context, index) {
final project = projects[index];
return ProjectItem(
project: project,
onDismissed: (direction) {
BlocProvider.of<ProjectsBloc>(context)
.add(DeleteProject(project, widget.user.company));
Scaffold.of(context).showSnackBar(DeleteProjectSnackBar(
project: project,
onUndo: () => BlocProvider.of<ProjectsBloc>(context)
.add(AddProject(project, widget.user.company)),
));
},
onTap: () async {
BlocProvider.of<CurrentProjectBloc>(context)
.add(GetCurrentProject(project));
},
onCheckboxChanged: (_) {
BlocProvider.of<ProjectsBloc>(context).add(
UpdateProject(project.copyWith(complete: !project.complete),
widget.user.company),
);
},
);
},
);
} else {
return Container();
}
},
);
}
}
Добавить экран проекта
class AddEditScreen extends StatefulWidget {
final bool isEditing;
//final OnSaveCallback onSave;
final Project project;
final User user;
AddEditScreen({
Key key,
//@required this.onSave,
@required this.isEditing,
@required this.user,
this.project,
}) : super(key: key);
@override
_AddEditScreenState createState() => _AddEditScreenState();
}
class _AddEditScreenState extends State<AddEditScreen> {
static final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
ProjectsBloc _projectsBloc;
@override
void initState() {
super.initState();
_projectsBloc = BlocProvider.of<ProjectsBloc>(context);
}
String _name;
String _user;
bool get isEditing => widget.isEditing;
User get _userName => widget.user;
@override
Widget build(BuildContext context) {
final textTheme = Theme.of(context).textTheme;
return BlocBuilder<ProjectsBloc, ProjectsState>(
builder: (context, state) {
return Scaffold(
appBar: AppBar(
title: Text(
isEditing ? 'Edit Project' : 'Add Project',
),
),
body: Padding(
padding: EdgeInsets.all(16.0),
child: Form(
key: _formKey,
child: ListView(
children: [
TextFormField(
initialValue: isEditing ? widget.project.name : '',
autofocus: !isEditing,
style: textTheme.headline,
decoration: InputDecoration(
hintText: 'Please Enter The Name Of The Project?',
),
validator: (val) {
return val.trim().isEmpty ? 'Please enter some text' : null;
},
onSaved: (value) => _name = value,
),
TextFormField(
initialValue:
isEditing ? widget.project.user : _userName.username,
style: textTheme.subhead,
decoration: InputDecoration(
hintText: 'Please ',
),
onSaved: (value) => _user = value,
)
],
),
),
),
floatingActionButton: FloatingActionButton(
tooltip: isEditing ? 'Save changes' : 'Add Todo',
child: Icon(isEditing ? Icons.check : Icons.save),
onPressed: () {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
//widget.onSave(_name, _user, false);
//BlocProvider.of<ProjectsBloc>(context).
_onFormSubmitted();
_projectsBloc.asBroadcastStream();
Navigator.of(context).pop();
}
},
),
);
}
);
}
void _onFormSubmitted() {
_projectsBloc.add(
AddProject(
Project(_user, name: _name, complete: false),
_userName.company
),
);
}
}