Why is ChangeNotifier updating endlessly

Viewed 42

I have 2 data provider classes that extend ChangeNotifier. Within each, there's a function to fetch data and at the end of them, I use notifyListeners() to notify the screens/listeners that the data changed. However, it seems that the listeners start getting notified endlessly instead of once and that creates a loop of reloading, circle indicators that don't go away, and a frozen screen. I don't get it.

Data providers:

class UsersDataProvider extends ChangeNotifier {
  UsersDataProvider() : super();

  static Map<int, QueryDocumentSnapshot<Object?>> usersMap = {};

  Future<void> fetchUsers() async {
    final userRef = FirebaseFirestore.instance.collection('users');

    final QuerySnapshot result = await userRef.get();

    final docs = result.docs.asMap();

    usersMap = docs;
    print(usersMap.length);
    notifyListeners();
  }
}

class PostsDataProvider extends ChangeNotifier {
  PostsDataProvider() : super();

  static Map<int, QueryDocumentSnapshot<Object?>> postsMap = {};

  Future<void> fetchPosts() async {

    UsersDataProvider.usersMap.forEach((index, resultValue) async {
      final postsRef = FirebaseFirestore.instance
          .collection('users')
          .doc(resultValue.id)
          .collection('posts');
      final QuerySnapshot postsResult = await postsRef.get();
      final postDocs = postsResult.docs.asMap();

      postsMap = postDocs;
      print('Post map: ${postsMap.length}');
      notifyListeners();
    });
  }
}

Add listeners and reload data:

Future<void> fetchUsersAndPosts(bool initial) async {

    if (!initial) {
      setState(() {
        postsLoading = true;
      });
      usersDataProvider.fetchUsers();
      postsDataProvider.fetchPosts();
    }

    if (initial) {
      usersDataProvider.addListener(() {
        print('changed');
        setState(() {
          fetchUsersAndPosts(false);
        });
      });
    }

    if (initial) {
      postsDataProvider.addListener(() {
        setState(() {
          fetchUsersAndPosts(false);
        });
      });
    }

    UsersDataProvider.usersMap.forEach((index, value) async {

      List<Post> posts = [];

      PostsDataProvider.postsMap.forEach((index, value) {
        final post = Post.fromJson(value.data() as Map<String, dynamic>);

        posts.add(post);

        setState(() {});

        if (posts.length == PostsDataProvider.postsMap.length) {
          setState(() {
            postsList = posts;
            postsList.sort((a, b) {
              return b.date.compareTo(a.date);
            });
            postsLoading = false;
          });
        }
      });

      final profileInfo =
      ProfileInfoObject.fromJson(value.data() as Map<String, dynamic>);

      Profile profile = Profile(profileInfo, postsList.where((p) => p.uid == value.id).toList());

      UserSearchResult user = (UserSearchResult(profile, value.id));

      if (usersList.where((u) => u.uid == user.uid).toList().isEmpty) {
        setState(() {
          usersList.add(user);
        });
      }
    });

    setState(() {
      postsList.sort((a, b) {
        return b.date.compareTo(a.date);
      });
    });
  }
0 Answers
Related