【问题标题】:Problem with events in BLoC Flutter. I always call two events instead of oneBLoC Flutter 中的事件问题。我总是调用两个事件而不是一个
【发布时间】:2022-01-13 20:39:58
【问题描述】:

我在每个块方法中使用 TodoLoadedState 列表返回状态。但是当我在 onPressed 中调用 block 事件时,不会返回列表本身,我必须向 block 方法添加第二次调用 todoBloc.add(LoadTodos());但这是不正确的。想法需要触发 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));
    });
  }
}

待办事项列表

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());
                    },

主页

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 {}

event onPressed,在任何地方你都必须使用 2 个事件来加载更新的列表

todoBloc.add(UpdateTodos(updateTodo));
todoBloc.add(LoadTodos());

【问题讨论】:

  • 您使用的是什么版本的 bloc?您还可以在问题中包含您的Todo 课程吗?
  • 我使用flutter_bloc:^8.0.1。所有相关代码都添加到问题中。如果您能提供帮助,我将不胜感激)

标签: flutter dart flutter-layout


【解决方案1】:

这是罪魁祸首:

abstract class TodoState extends Equatable {
  const TodoState();

  @override
  List<Object> get props => [];
}

您在TodoState 中扩展Equatable,并将一个空列表传递给props。当 TodoLoadedState 等其他状态扩展 TodoState 时,它们也会继承 Equatable 和空属性。

如果您使用的是 Equatable,请确保将所有属性传递给 道具吸气剂。

这是来自集团faq。现在你的TodoLoadedState 的所有实例都被认为是平等的。不管你有一个TodoLoadedState 有数百个loadedUser 还是一个TodoLoadedState 没有。它们都被认为是相等的,只有当您第一次通过新的 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];
}

【讨论】:

  • 你帮了我很多。非常感谢:)
猜你喜欢
  • 2020-04-29
  • 2020-11-12
  • 2017-10-17
  • 2021-04-20
  • 1970-01-01
  • 2021-04-25
  • 2020-02-18
  • 2023-02-17
  • 2020-12-06
相关资源
最近更新 更多