2

I'm working on a Flutter project which uses GetX for state management.

We have some entities which contains List properties. A simplified version would be similar to this:

class UserFees extends Equatable {
  final String userId;
  final List<double> fees;
  UserFees({required this.userId, this.fees = const []});

  void addFee(double newFee) => fees.add(newFee);

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

  // Alternatively, we have also tried to:
  @override
  bool operator ==(Object other) =>
    identical(this, other) ||
    other is UserFees &&
    runtimeType == other.runtimeType &&
    listEquals(fees, (other as UserFees).fees);

  @override
  int get hashCode => // I do not remember the calculus we'd used,
                      // but it did at least change when new item was added;
}

This entity is used in the controller:

class MyController extends GetxController {
  final Rx<UserFees> userFees;

  void addFee(double newFee) {
    userFees.addFee(newFee);
    // We have tried calling update() to no effect
  }
}

When I use this inside a Widget with Obx, it doesn't rebuild when I add an item to the list, even though the object's hashCode gets updated.

Widget build(BuildContext context) {
  return Scaffold(
    body: Obx(() => Column(children:
        ...controller.userFees.fees.map(
            (item) => Text(item.toString()
          );
        ),
      ),
    floatingActionButton: IconButton(
        icon: const Icon(Icons.add),
        onPressed: controller.addFee(0.1)
      ),
    );
  );
}

Our team has made this work by turning the List inside the entity into an RxList, however it's not ideal because we did not want to couple our entities with GetX or RxDart.

GetX documentation is pretty poor on these details, and the source code ir pretty hard to understand, at least for me. So, can anyone explain to me how is it that Obx knows that an observable object has changed? Does it look at the hashCode? Will it only rebuild if my class is immutable, and I rebuild the object entirely when adding an item to the list?

Eric Omine
  • 489
  • 4
  • 15

1 Answers1

1

There are some suggestions which I feel could help you.

In the MyController, you are using

 final Rx<UserFees> userFees;

which means you are declaring as an Rx, but you are not making it observables. To make your UserFees observables, you should use

 final Rx<UserFees> userFees = 0.0.obs; // if it's type is double;

Next, In your entity, if you think there is some variable who's value is changing and you want to reflect that value in the UI. Then you should also make that Observable.

Rohit Singh
  • 411
  • 3
  • 15
  • 1
    I would say calling `userFees.refresh()` might also be in order since `UserFees` is a class. – Nathaniel Johnson Oct 02 '21 at 20:50
  • @RohitSingh I think the UserFees entity hint will probably be useful, thanks. About making the variables inside the entity also observable, that's what we did and we did not want to do that, because the entity gets coupled to GetX. Our company often reuses code between projects, but not all projects use GetX. – Eric Omine Oct 04 '21 at 13:44
  • @NathanielJohnson I think your hint will be useful too, thanks. – Eric Omine Oct 04 '21 at 13:46
  • @NathanielJohnson you dont need to use userFees.refresh() if you are using Obx() widget. Because Obx() will automatically update the widget when it needs. If you are using GetBuilder((controller) => SomeWidget()); then in that case, you manually need to refresh the UI. – Rohit Singh Oct 04 '21 at 17:14
  • Obx (and everyone else) doesn't do deep refresh on Lists inside of objects. It is always a problem. I have stopped using observables for just this reason and simply refresh/update/notifyListeners in the controller. – Nathaniel Johnson Oct 04 '21 at 20:47
  • @NathanielJohnson Sorry, I am not agree with you. If your Obx() widget is not refreshing list automatically, then there might be some another problem. I want to suggest you to go through this [documentation](https://github.com/jonataslaw/getx/blob/master/documentation/en_US/state_management.md). – Rohit Singh Oct 05 '21 at 02:48