Problem using firebase Listen with mobx

Asked

Viewed 32 times

1

Hello, good afternoon!

I am trying to make a query on firebase using Listen to be notified every time a document is changed. However, Listen is always notified but the widget itself is not, even using Observer.

The widget is only changed with the firebase update if I change tab and return to it, which shouldn’t be happening. Yeah, I’m looking at the list with the mobx..

Initstate:

@override
  void initState() {
    super.initState();
    addPedidosListener();
  }

Build:

@override
  Widget build(BuildContext context) {

    final _pedidosBloc = BlocProvider.of<PedidosBloc>(context);

    return Observer(
      builder: (_){
        return ListView.builder(
          itemCount: pedidosModel.listPedidos.length,
          itemBuilder: (context, index){

            if(index == 0){
              return Column(
                children: [
                  _parteFiltro(_pedidosBloc),
                  CardPedido(pedidosModel.listPedidos[index])
                ],
              );
            }

            return CardPedido(pedidosModel.listPedidos[index]);
          },
        );
      },
    );
  } 

Listen:

Future<void> addPedidosListener() async{
Pedido pedido;
FirebaseFirestore.instance.collection("pedidos").doc("Kwdqc77luBnyPdS2AqD4").collection("pedidos").snapshots().listen((snapshot) {

  snapshot.docChanges.forEach((change) {
    String pedidoId = change.doc.id;


    pedido = Pedido.fromDocumentSnapshot(change.doc);

    switch(change.type){
      case DocumentChangeType.added:
      //========== quando um pedido for adicionado ==========
        pedidosModel.addPedido(pedido);
        break;
      case DocumentChangeType.modified:
      //========== modificado ==========
        print("modificou");
        print(pedido.status);
        Pedido pedidoGlobal = Pedido.recuperarPedidoGlobal();
        if(pedidoGlobal != null && pedido.idPedido == pedidoGlobal.idPedido){
          Pedido.setarPedidoGlobal(pedido);
        }

        pedidosModel.removeWhere(pedidoId);
        pedidosModel.addPedido(pedido);
        break;
      case DocumentChangeType.removed:
      //========== removido ==========
        pedidosModel.removeWhere(pedidoId);
        break;
    }
  });

  //_sort();

});

}

Mobx:

part 'PedidosModel.g.dart';

class PedidosModel = _PedidosModel with _$PedidosModel;

abstract class _PedidosModel with Store{

  @observable
  List<Pedido> listPedidos = [];

  @action
  void addPedido(Pedido value){
    listPedidos.add(value);
  }

  @action
  void removeWhere(pedidoId){
    listPedidos.removeWhere((pedido) => pedido.idPedido == pedidoId);
  }

}

1 answer

2


On the Mobx issue, working with reactive lists requires a small change

Instead of using a simple list, like this one:

List<Pedido> listPedidos = [];

You need to use a ObservableList, thus:

ObservableList<Pedido> listPedidos = <Pedido>[].asObservable();

I leave below the complete code of yours Store:

part 'PedidosModel.g.dart';

class PedidosModel = _PedidosModel with _$PedidosModel;

abstract class _PedidosModel with Store{

  @observable
  ObservableList<Pedido> listPedidos = <Pedido>[].asObservable();

  @action
  void addPedido(Pedido value){
    listPedidos.add(value);
  }

  @action
  void removeWhere(pedidoId){
    listPedidos.removeWhere((pedido) => pedido.idPedido == pedidoId);
  }

}

Explanation

To Observablelist is watching her items, so when a new one is added or deleted she notifies the Observer that something happened.

Attention: This type of list will not hear changes made in properties of each item of it, for example, if you change the status of any of the items on the list, nothing will be notified.

If you want to use "normal" lists, as I was already doing List<Pedido>, a new list needs to be set on the property listPedidos every change in your items, as in the example below:

  @action
  void addPedido(Pedido value){
    listPedidos.add(value);
    listPedidos = List.from(listPedidos);
  }

Browser other questions tagged

You are not signed in. Login or sign up in order to post.