BLoC Flutter 中的事件问题。我总是调用两个事件而不是一个
Problem with events in BLoC Flutter. I always call two events instead of one
我return在每个块方法中使用 TodoLoadedState 列表的状态。但是当我在 onPressed 中调用 block 事件时,列表本身不是 returned 并且我必须添加对 block 方法的第二次调用 todoBloc.add(LoadTodos());但那是不正确的。 idea需要触发1个事件但是要执行2个动作,第二个动作是更新列表。提前致谢!
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
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 {}
事件onPressed,到处都要用2个事件来加载更新列表
todoBloc.add(UpdateTodos(updateTodo));
todoBloc.add(LoadTodos());
这是罪魁祸首:
abstract class TodoState extends Equatable {
const TodoState();
@override
List<Object> get props => [];
}
您正在 TodoState
中扩展 Equatable
并将一个空列表传递给 props
。当 TodoLoadedState
等其他状态扩展 TodoState
时,它们也会继承 Equatable
和空属性。
If you're using Equatable make sure to pass all properties to the
props getter.
这来自集团 faq。现在你的 TodoLoadedState
的所有实例都被认为是平等的。无论您是 TodoLoadedState
和数百个 loadedUser
还是 TodoLoadedState
和 none 都没有关系。它们都被认为是相等的,只有在您第一次传递新的 TodoLoadedState
时,BlocBuilder
才会更新。随后的那些没有效果,因为 BlocBuilder
认为它与前一个相同。您的 LoadTodos
事件导致重建的原因是您首先发出 TodoLoadingState()
,然后在成功的情况下发出 TodoLoadedState(loadedUser: _loadedTodoList)
。两种不同状态之间的这种交替使其起作用。
所以要么不要使用 Equatable
,要么确保将所有属性传递给 props
。
class TodoLoadedState extends TodoState {
final List<dynamic> loadedUser;
TodoLoadedState({required this.loadedUser});
@override
List<Object?> get props => [loadedUser];
}
我return在每个块方法中使用 TodoLoadedState 列表的状态。但是当我在 onPressed 中调用 block 事件时,列表本身不是 returned 并且我必须添加对 block 方法的第二次调用 todoBloc.add(LoadTodos());但那是不正确的。 idea需要触发1个事件但是要执行2个动作,第二个动作是更新列表。提前致谢!
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
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 {}
事件onPressed,到处都要用2个事件来加载更新列表
todoBloc.add(UpdateTodos(updateTodo));
todoBloc.add(LoadTodos());
这是罪魁祸首:
abstract class TodoState extends Equatable {
const TodoState();
@override
List<Object> get props => [];
}
您正在 TodoState
中扩展 Equatable
并将一个空列表传递给 props
。当 TodoLoadedState
等其他状态扩展 TodoState
时,它们也会继承 Equatable
和空属性。
If you're using Equatable make sure to pass all properties to the props getter.
这来自集团 faq。现在你的 TodoLoadedState
的所有实例都被认为是平等的。无论您是 TodoLoadedState
和数百个 loadedUser
还是 TodoLoadedState
和 none 都没有关系。它们都被认为是相等的,只有在您第一次传递新的 TodoLoadedState
时,BlocBuilder
才会更新。随后的那些没有效果,因为 BlocBuilder
认为它与前一个相同。您的 LoadTodos
事件导致重建的原因是您首先发出 TodoLoadingState()
,然后在成功的情况下发出 TodoLoadedState(loadedUser: _loadedTodoList)
。两种不同状态之间的这种交替使其起作用。
所以要么不要使用 Equatable
,要么确保将所有属性传递给 props
。
class TodoLoadedState extends TodoState {
final List<dynamic> loadedUser;
TodoLoadedState({required this.loadedUser});
@override
List<Object?> get props => [loadedUser];
}