dev.farmer
dev.farmer

Reputation: 2809

Flutter: My list view is not updated when I modify an item

I am developing a 'todo' flutter app using BloC Architecture pattern.

My 'Home' ui displays todo list, and user can click the item's button to change the status from "todo" to "complete".

When an item is completed, it should display with another color distinct from other todos not completed.

But when I click the "complete" button, the list view is not updated.

Below is my UI code:

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

And here is my BloC class:

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

}

Upvotes: 0

Views: 3225

Answers (1)

Ferdi
Ferdi

Reputation: 788

It's because you don't "refresh" your list after calling getTodos() here's the modification:

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

As I mention in the comment you can remove the _todos buffer but I don't want to refract to much you code.

With these few adjustents it's should work. Hope it's help !!

Upvotes: 2

Related Questions