Flutter: мой вид списка не обновляется при изменении элемента

#dart #flutter #bloc

#дротик #флаттер #блок

Вопрос:

Я разрабатываю приложение flutter ‘todo’, используя шаблон блочной архитектуры.

Мой пользовательский интерфейс «Home» отображает список задач, и пользователь может нажать кнопку элемента, чтобы изменить статус с «todo» на «завершено».

Когда элемент завершен, он должен отображаться другим цветом, отличным от других незавершенных задач.

Но когда я нажимаю кнопку «Завершить», представление списка не обновляется.

Ниже приведен мой код пользовательского интерфейса:

 class HomePage extends StatelessWidget {
  final TodoRepository _todoRepository;
  final HomeBloc bloc;

  HomePage(this._todoRepository) : this.bloc = HomeBloc(_todoRepository);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: StreamBuilder<List<Task>>(
            stream: bloc.todos,
            builder: (context, snapshot) {
              return ListView(
                children: snapshot.data.map(_buildItem).toList(),
              );
            }),
      ),
    );
  }

  Widget _buildItem(Todo todo) {
    if (todo.complete) {
      return completed(todo);
    } else {
      return inCompleted(todo);
    }
  }

  Widget inCompleted(Todo todo) {
    return MaterialButton(
      textColor: Colors.white,
      color: Colors.green,
      child: Text("Complete"),
      onPressed: () {
        bloc.done.add(todo);
      }
    );
  }

  Widget completed(Todo todo) {
    return MaterialButton(
      textColor: Colors.white,
      color: Colors.red,
      child: Text("Cancel"),
      onPressed: () {
        bloc.done.add(todo);
      }
    );
  }
}

  

И вот мой класс блока:

 class HomeBloc {

  final _getTodosSubject = PublishSubject<List<Todo>>();
  final _doneTodoSubject = PublishSubject<Todo>();
  final _cancelTodoSubject = PublishSubject<Todo>();

  final TodoRepository _todoRepository;

  var _todos = <Todo>[];

  Stream<List<Todo>> get todos => _getTodosSubject.stream;

  Sink<Todo> get done => _doneTodoSubject.sink;

  Sink<Todo> get cancel => _doneTodoSubject.sink;

  HomeBloc(this._todoRepository) {
    _getTodos().then((_) {
      _getTodosSubject.add(_todos);
    });

    _doneTodoSubject.listen(_doneTodo);

    _cancelTodoSubject.listen(_cancelTodo);
  }

  Future<Null> _getTodos() async {
    await _todoRepository.getAll().then((list) {
      _todos = list;
    });
  }

  void _doneTodo(Todo todo) {
    todo.complete = true;
    _update(todo);
  }

  void _cancelTodo(Todo todo) async {
    todo.complete = false;
    _update(todo);
  }

  void _update(Todo todo) async {
    await _todoRepository.save(todo);
    _getTodos();
  }

}
  

Ответ №1:

Это потому, что вы не «обновляете» свой список после вызова getTodos() вот изменение:

 HomeBloc(this._todoRepository) {
    _getTodos() //Remove the adding part it's done in the function

    _doneTodoSubject.listen(_doneTodo);

    _cancelTodoSubject.listen(_cancelTodo);
  }

  Future<Null> _getTodos() async {
    await _todoRepository.getAll().then((list) {
      _todos = list;
      _getTodosSubject.add(list); //You can actually remove the buffer _todos object 
    });
  }
  

Как я упоминал в комментарии, вы можете удалить _todos буфер, но я не хочу сильно отвлекаться на ваш код.

С этими несколькими настройками это должно сработать. Надеюсь, это поможет!!

Комментарии:

1. Спасибо, это работает! _getTodosSubject.sink.add(список); тоже работает. Знаете ли вы, в чем различия между ними?