[英]Problem with events in BLoC Flutter. I always call two events instead of one
I return the state with the TodoLoadedState list in each block method.我在每个块方法中返回带有 TodoLoadedState 列表的 state。 But when I call the block event in onPressed, the list itself is not returned and I have to add a second call to the block method todoBloc.add(LoadTodos());但是当我在 onPressed 中调用 block 事件时,不会返回列表本身,我必须向 block 方法添加第二次调用 todoBloc.add(LoadTodos()); But that's not correct.但这是不正确的。 Ideas need to trigger 1 event but to perform 2 actions, the second action is to update the list.想法需要触发 1 个事件但要执行 2 个动作,第二个动作是更新列表。 Thanks in advance!提前致谢!
todo_bloc待办事项块
class TodoBloc extends Bloc<TodoEvent, TodoState> {
final TodoRepository todoRepository;
TodoBloc(this.todoRepository) : super(TodoEmptyState()) {
on<LoadTodos>((event, emit) async {
emit(TodoLoadingState());
try {
final List<Todo> _loadedTodoList = await todoRepository.getAllTodos();
emit(TodoLoadedState(loadedUser: _loadedTodoList));
} catch (_) {
emit(TodoErrorState());
}
});
on<CreateTodos>((event, emit) async {
// Todo todo = Todo(description: event.task, isDone: false);
await todoRepository.insertTodo(event.todo);
final List<Todo> _loadedTodoList = await todoRepository.getAllTodos();
emit(TodoLoadedState(loadedUser: _loadedTodoList));
});
on<DeleteTodos>((event, emit) async {
await todoRepository.deleteTodo(event.id);
final List<Todo> _loadedTodoList = await todoRepository.getAllTodos();
emit(TodoLoadedState(loadedUser: _loadedTodoList));
});
on<UpdateTodos>((event, emit) async {
await todoRepository.updateTodo(event.todo);
final List<Todo> _loadedTodoList = await todoRepository.getAllTodos();
emit(TodoLoadedState(loadedUser: _loadedTodoList));
});
}
}
todo_list待办事项列表
class TodoList extends StatelessWidget {
@override
Widget build(BuildContext context) {
final TodoBloc todoBloc = context.read<TodoBloc>();
return BlocBuilder<TodoBloc, TodoState>(builder: (context, state) {
if (state is TodoEmptyState) {
return const Center(
child: Text(
'No Todo',
style: TextStyle(fontSize: 20.0),
),
);
}
if (state is TodoLoadingState) {
return const Center(child: CircularProgressIndicator());
}
if (state is TodoLoadedState) {
return ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: state.loadedUser.length,
itemBuilder: (context, index) => ListTile(
title: Column(children: [
Text('${state.loadedUser[index].description}'),
Text('${state.loadedUser[index].id}'),
]),
trailing: IconButton(
onPressed: () {
todoBloc.add(DeleteTodos(id: state.loadedUser[index].id));
todoBloc.add(LoadTodos());
},
home_page主页
class HomePage extends StatelessWidget {
final todoRepository = TodoRepository();
@override
Widget build(BuildContext context) {
return BlocBuilder<TodoBloc, TodoState>(builder: (context, state) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter Todos'),
),
body: SingleChildScrollView(
child: Column(
children: [
TodoList(),
],
),
),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add, size: 32, color: Colors.white),
onPressed: () {
final TodoBloc todoBloc = context.read<TodoBloc>();
final _todoDescriptionFromController = TextEditingController();
showModalBottomSheet(
context: context,
builder: (builder) {
return Padding(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
child: Container(
color: Colors.transparent,
child: Container(
todo_state todo_state
abstract class TodoState extends Equatable {
const TodoState();
@override
List<Object> get props => [];
}
class TodoLoadingState extends TodoState {}
class TodoEmptyState extends TodoState {}
class TodoLoadedState extends TodoState {
List<dynamic> loadedUser;
TodoLoadedState({required this.loadedUser});
}
class TodoErrorState extends TodoState {}
todo_event待办事项
abstract class TodoEvent extends Equatable {
const TodoEvent();
@override
List<Object> get props => [];
}
class LoadTodos extends TodoEvent {}
class CreateTodos extends TodoEvent {
final Todo todo;
const CreateTodos(this.todo);
}
class UpdateTodos extends TodoEvent {
final Todo todo;
const UpdateTodos(this.todo);
}
class DeleteTodos extends TodoEvent {
final int id;
const DeleteTodos({required this.id});
}
class QueryTodo extends TodoEvent {}
event onPressed, everywhere you have to use 2 events to load the updated list事件 onPressed,在任何地方你都必须使用 2 个事件来加载更新的列表
todoBloc.add(UpdateTodos(updateTodo));
todoBloc.add(LoadTodos());
This is the culprit:这是罪魁祸首:
abstract class TodoState extends Equatable {
const TodoState();
@override
List<Object> get props => [];
}
You are extending Equatable
in TodoState
and passing an empty list to props
.您正在扩展Equatable
中的TodoState
并将一个空列表传递给props
。 When other states such as TodoLoadedState
extend TodoState
they inherit Equatable
as well and the empty props.当其他状态(例如TodoLoadedState
扩展TodoState
时,它们也会继承Equatable
和空属性。
If you're using Equatable make sure to pass all properties to the props getter.如果您使用 Equatable,请确保将所有属性传递给 props getter。
This is from bloc faq .这是来自 bloc常见问题解答。 Right now all instances of your TodoLoadedState
are considered equal.现在你的TodoLoadedState
的所有实例都被认为是相等的。 Doesn't matter if you have a TodoLoadedState
with hundreds of loadedUser
or a TodoLoadedState
with none.如果您有一个TodoLoadedState
有数百个loadedUser
或一个TodoLoadedState
没有,都没有关系。 They are both considered equal and only the first time you pass a new TodoLoadedState
the BlocBuilder
will update.它们都被认为是相等的,并且只有在您第一次传递新的TodoLoadedState
时, BlocBuilder
才会更新。 The consequent ones have no effect since BlocBuilder
thinks it is the same as previous one.后续的没有效果,因为BlocBuilder
认为它与前一个相同。 The reason your LoadTodos
event causes a rebuild is that first you emit TodoLoadingState()
and then in case of success TodoLoadedState(loadedUser: _loadedTodoList)
.您的LoadTodos
事件导致重建的原因是首先您发出TodoLoadingState()
,然后在成功的情况下发出 TodoLoadedState TodoLoadedState(loadedUser: _loadedTodoList)
。 This alternating between two different states makes it work.这种在两种不同状态之间的交替使其工作。
So either don't use Equatable
or make sure to pass all the properties to props
.所以要么不要使用Equatable
,要么确保将所有属性传递给props
。
class TodoLoadedState extends TodoState {
final List<dynamic> loadedUser;
TodoLoadedState({required this.loadedUser});
@override
List<Object?> get props => [loadedUser];
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.