Search code examples
flutterfirebasedartfirebase-realtime-databaseflutter-getx

GetX Controller - Wait for firebase RTDB stream to be populated


I am new to GetX and want to get some concepts right. This is my process to get the groups that a current user is in using Firebase Realtime Database:

  1. Create an AuthController to get current user id (works perfectly)

    class AuthController extends GetxController {
      FirebaseAuth auth = FirebaseAuth.instance;
    
      Rx<User?> firebaseUser = Rx<User?>(FirebaseAuth.instance.currentUser);
    
      User? get user => firebaseUser.value;
    
      @override
      void onInit() {
        firebaseUser.bindStream(auth.authStateChanges());
        super.onInit();
      }
    } ```
    
    
    
  2. Create a UserController to get ids of groups that the user has (working partially)

class FrediUserController extends GetxController {
  Rx<List<String>> groupIdList = Rx<List<String>>([]);

  List<String> get groupIds => groupIdList.value;

  @override
  void onInit() {
    User? user = Get.find<AuthController>().user;

    if (user != null) {
      String uid = user.uid;
      groupIdList.bindStream(DatabaseManager().userGroupIdsStream(uid));
      print(groupIds); //prints [] when it should be populated
    }
    super.onInit();
  }
}
  1. Create a GroupsController to get the groups from those ids (not working) --> Dependant on UserController to have been populated with the id's.
class FrediGroupController extends GetxController {
  Rx<List<FrediUserGroup>> groupList = Rx<List<FrediUserGroup>>([]);

  List<FrediUserGroup> get groups => groupList.value;

  void bindStream() {}

  @override
  void onInit() {
    final c = Get.find<FrediUserController>();
    List<String> groupIds = c.groupIds;
    print(groupIds); //prints [], when it should have ids
    groupList.bindStream(DatabaseManager().groupsStream(groupIds)); //won't load anything without id's

    super.onInit();
  }
}

Observations

  • Get.put is called sequentially in the main.dart file:
  Get.put(AuthController());
  Get.put(FrediUserController());
  Get.put(FrediGroupController());
  • Inside my HomePage() Stateful Widget, if I call the UserController, the data loads correctly:
    GetX<FrediUserController>(
                  builder: (controller) {
                    List<String> groups = controller.groupIds;
                     print(groups); //PRINTS the list of correct ids. THE DATA LOADS.
                    return Expanded(
                      child: ListView.builder(
                        shrinkWrap: true,
                        itemCount: groups.length,
                        itemBuilder: (context, index) {
        return Text('${groups[index]}', 
               style: TextStyle(color: Colors.white));
                                                        },),); },),

QUESTION

It is as if the stream takes some time to populate, but the UserController doesn't wait for it and initializes the controller as empty at first, but after some time it populates (not in time to pass the data to the GroupController.

How can I fix this? I have tried async but not with much luck.

Behaviour I would Like:

  • Streams may/may not be ready, so it can initialize as empty or not.
  • HOWEVER, if the stream arrives, everything should be updted, including the initialization of controllers that depend on UserController like GroupController.
  • Consequently, the UI is rebuilt with new values.

THANK YOU!


Solution

  • There are two things that you can add:

    1. Future Builder to show some loading screen while it fetch data from RTDB
    2. ever function
    class AuthController extends GetxController {
    late Rx<User?> firebaseuser;
    
      @override
      void onReady() {
        super.onReady();
        firebaseuser = Rx<User?>(FirebaseAuth.instance.currentUser);
        firebaseuser.bindStream(FirebaseAuth.instance.idTokenChanges());
        ever(firebaseuser, _setInitialScreen);
      }
    
      _setInitialScreen(User? user) {
    
        if (user != null) {
          //User Logged IN
          
        } else {
          //User Logged out
          
        }
      }
    }