Problem using Mobx and Observerlist

Asked

Viewed 77 times

3

Hello, good afternoon!

I am trying to make a checkbox list (Checkboxlisttile) using mobx, however, whenever I click on the box to mark or deselect I have to use the flutter Reload or setState to update the data.

mobx is not automatically updating using Observer, I don’t know why. Could you help me?

My model:

part 'ItemComplementoModel.g.dart';
 
class ItemComplementoModel = _ItemComplementoModel with _$ItemComplementoModel;
 
abstract class _ItemComplementoModel with Store{
 
  @observable
  ObservableList<Map<String, dynamic>> listaItens = ObservableList<Map<String, dynamic>>();
 
  @action
  void addItem(Map<String, dynamic> novoItem){
    listaItens.add(novoItem);
  }
 
  @action
  void marcarItem(int indice, bool marcou, ItemComplemento itemComplemento){
    print("marcou");
    //listaItens[indice]["marcou"] = marcou;
 
      print(listaItens);
      print("depois...");
      listaItens[indice]["marcou"] = marcou;
      print(listaItens);
 
  }
 
}    

My Observer:

_parteItemComplemento(int indice, ItemComplemento itemComplemento){

  return Observer(
    builder: (_){
      return CheckboxListTile(
        onChanged: (marcou){
          //setState(() {
          //_listaItensComplementos[indice]["marcou"] = marcou;
          itemComplementoModel.marcarItem(indice, marcou, itemComplemento);
          print("marcou: ${marcou}");
          //_saveData();
          //});
        },
        title: Text(itemComplemento.nome),
        //value: _listaItensComplementos[indice]["marcou"],
        value: itemComplementoModel.listaItens[indice]["marcou"],
        secondary: CircleAvatar(
          child: Icon(
              itemComplementoModel.listaItens[indice]["marcou"]
                  ? Icons.check
                  : Icons.error
          ),
        ),
      );
    },
  );
}
  • 1

    If you’re using the Mobx it is not necessary to use the setState()... Your problem, I believe, taking a look at it, I think it’s because you’re using a Observablelist of the kind Map, the list is updated when the reference of an object of it changes, and in your case you are only changing a value of an object of the Map, thus the reference of the same does not change. If you change the marcarItem, for example, to: listaItens[indice] = {"marcou": false}; or listaItens[indice] = {"marcou": true}; should work.

  • Perfect! Problem solved, thank you very much.

  • 1

    I got a little time to produce a more detailed answer! From a look later.

2 answers

2


First, when you use the Mobx, inside the Widget Observer no need to use the setState().

Observerlist

This type of list, will be listening to the change in the reference of each object it contains; so every time an object is changed, the Observer will be notified to update on screen.

Resolution

In your case, you’re working with the following

@observable
ObservableList<Map<String, dynamic>> listaItens = ObservableList<Map<String, dynamic>>();

And when you click on some Checkbox you fire the following function:

  @action
  void marcarItem(int indice, bool marcou, ItemComplemento itemComplemento){
      listaItens[indice]["marcou"] = marcou;    
  }

Your problem is that as it is being done, your list is not notifying you of the item’s change as the item’s reference has not changed. What you are doing is simply changing the value of an object from Map.

For it to work properly, the way it’s done there, you need to make a little adjustment:

  @action
  void marcarItem(int indice, bool marcou, ItemComplemento itemComplemento) {
      if (marcou)
        listaItens[indice] = {"marcou": true};
      else
        listaItens[indice] = {"marcou": false};    
  }

In this way, the list will notify the Observer that there has been a change in the object reference and that it is necessary to update the layout.

  • 1

    Your answer was simply perfect, Matheus.

  • One last question, I’m doing it now with an object and I’m having the same problem. My list only updates if I use setState, which shouldn’t happen. How can I notify the list in the case of an object? I’m new around here and I don’t know if I should ask a new question.

  • 1

    What would be this "Object"? You changed the ObserverList<Map<String, dynamic>> for ObserverList<UmaClasse>?

  • Exactly. My bookmark looks something like this: Itemcomplemento itemComplemento = listItens[Indice]; print(itemComplemento.nome); itemComplemento.tagged = marked;

  • 1

    The interesting thing is that each question is a question. But in your case I advise you first, take a look at my Github repository Campo Minado. There I work with a similar scheme, you will be able to find an example in the files Fieldmodel and Minesweepercontroller

  • OK Matheus, I’ll ask another question. But thank you for your attention.

Show 1 more comment

-1

Perfect answer, Matheus! Thank you very much!

But in this case, I now need to use an object/class instead of the array to pick up other attributes more easily and organized.

So my model was like this:

abstract class _ItemComplementoModel with Store{

  @observable
  ObservableList<ItemComplemento> listaItens = ObservableList<ItemComplemento>();

  @action
  void addItem(ItemComplemento novoItem){
    listaItens.add(novoItem);
  }

  @action
  void marcarItem(int indice, bool marcou, CarrinhoModel carrinhoModel){

    ItemComplemento itemComplemento = listaItens[indice];
    print(itemComplemento.nome);
    itemComplemento.marcado = marcou;

  }

}

And my Observer:

_parteItemComplemento(int indice, ItemComplemento itemComplemento){
    return Observer(
      builder: (_){
        return CheckboxListTile(
          onChanged: (marcou){
            itemComplementoModel.marcarItem(indice, marcou, carrinhoModel);
            print("marcou ${marcou}");
          },
          title: Text(itemComplemento.nome),
          value: itemComplementoModel.listaItens[indice].marcado,
          secondary: CircleAvatar(
            child: Icon(
                itemComplementoModel.listaItens[indice].marcado
                    ? Icons.check
                    : Icons.error
            ),
          ),
        );
      },
    );
  }

However, I continue with the same previous problem, the list is only updated if I use setState, thing that should not happen.

  • 1

    This is a space for answers only, for "other problems" create new questions or if it is related to the main problem edit your question.

  • I’ve created this new question, Matheus: question. If you can help me I would be very grateful, I believe it is also change only one line of code, but I am not getting to a solution like the previous one.

Browser other questions tagged

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