mobxjs / mobx.dart

MobX for the Dart language. Hassle-free, reactive state-management for your Dart and Flutter apps.
https://mobx.netlify.app
MIT License
2.39k stars 310 forks source link

ObservableMap not notifying Observer mobx 2.2.3 it was woking fine in 2.2.1 #969

Closed boradparas closed 8 months ago

boradparas commented 9 months ago

I am using so many ObservableMaps in the app and none of them are updating the UI since I upgraded to 2.2.3

@observable ObservableMap<String, ParticipantExtended> sortedParticipants = ObservableMap<String, ParticipantExtended>();

Observer(
                          builder: (_) {
                            return SliverGrid(
                              gridDelegate:
                                  SliverGridDelegateWithFixedCrossAxisCount(
                                crossAxisCount: crossAxisCount,
                                childAspectRatio: tileWidth / tileHeight,
                                crossAxisSpacing: 2,
                                mainAxisSpacing: 2,
                              ),
                              delegate: SliverChildBuilderDelegate(
                                (context, index) {
                                  final participant = videoRoomStore
                                      .sortedParticipants.values
                                      .elementAt(index);
                                 return VisibilityDetector(
                                    key: Key(participant.identity),
                                    onVisibilityChanged: (info) {
                                      final bool isVisible =
                                          info.visibleFraction > 0;
                                      final bool isCompletelyGone =
                                          info.visibleFraction == 0;
                                      final bool isSubscribed = videoRoomStore
                                                  .participantSubscriptions[
                                              participant.identity] ??
                                          false;
                                      final bool shouldSubscribe =
                                          !isSubscribed &&
                                              isVisible &&
                                              !participant.isLocalParticipant;

                                      if (shouldSubscribe) {
                                        videoRoomStore.subscribeToVideoTracks(
                                          participant.participant
                                              as RemoteParticipant,
                                        );
                                        videoRoomStore.visibleParticipants[
                                            participant.identity] = true;
                                      } else if (!participant
                                              .isLocalParticipant &&
                                          isCompletelyGone) {
                                        videoRoomStore.unSubscribeToVideoTracks(
                                          participant.participant
                                              as RemoteParticipant,
                                        );
                                        videoRoomStore.visibleParticipants
                                            .remove(
                                          participant.identity,
                                        );
                                      }
                                    },
                                    child: ParticipantTile(
                                      participant: participant,
                                    ),
                                  );
                                },
                                childCount: videoRoomStore.isAppInForeground
                                    ? videoRoomStore.sortedParticipants.length
                                    : 0,
                              ),
                            );
                          },
                        ),

What change I need to make to keep it working as earlier it used to work?

amondnet commented 8 months ago

@boradparas The issue may be related to this PR. Since 2.2.3, mobx checks for equality of map, iterable with DeepCollectionEquality.

Could you try one of the following?

  1. use @alwaysNotify instead of @observable.
     @alwaysNotify 
     ObservableMap<String, ParticipantExtended> sortedParticipants = ObservableMap<String, ParticipantExtended>();
  2. override == and hashCode in ParticipantExtended. Avoid unnecessary observable notifications of Iterable or Map fields.
alxmoroz commented 8 months ago

Same for ObservableList etc.

How can I notify observer now, when changing attrs on objects within list or map? Equality checks only addresses in memory, but not theirs contents...

Is this tool only suitable for simple lists of strings and numbers? Previously, it was possible to work with objects.

amondnet commented 8 months ago

@alexggordon

How can I notify observer now, when changing attrs on objects within list or map? Equality checks only addresses in memory, but not theirs contents...

Can you please provide reproducible code? Then I can tell you how to do it. Alternatively, see the documentation.

Could you try one of the following?

  1. use @alwaysNotify.
  2. override == and hashCode in Object
  3. use immutable data class

https://github.com/mobxjs/mobx.dart/issues/851

amondnet commented 8 months ago

https://github.com/mobxjs/mobx.dart/pull/970

alxmoroz commented 8 months ago

@amondnet

Could you try one of the following?

  1. use @alwaysNotify.

I tried it. Without changes. Perhaps I didn’t fully understand how to apply it correctly.

  1. override == and hashCode in Object
  2. use immutable data class

Looks like a suitable solution. I'll try this approach. Thank you very much!

amondnet commented 8 months ago

https://github.com/mobxjs/mobx.dart/pull/971

Make the change in 2.2.3 optional. If you want the use this behavior , modify @observable to @MakeObservable(useDeepEquality: true).