Search code examples
firebasefluttergoogle-cloud-firestoreflutter-getxstream-builder

How to sequentially call the Getx controllers


My Task is :

  • I have an list of orders in firebase in users collection ,
  • I want to get information of those orders which is in orders collection,
  • And moment a list of order is updated in the firebase users collection.
  • The orders list should be automatically updated to get the latest information from the orders collection.

But for that i have to wait until list of orders is fetched from the users collection and only then i can query from orders collection about those orders.. I am stuck here,

And i want to actually understand Getx's bindStream , ever(), and observable variables,and Obx() is used in widget , But what if it is normal variable and i want to listen to it's changes ,how to do that, because Obx() can be only used while you use Widget

So far my code:

controllers.dart

UtilityController utilityController = UtilityController.instance;
CartController cartController = CartController.instance;
OrderController orderController = OrderController.instance;

UserModel.dart

class UserModel {
  String? uid;
  String? email;
  String? name;
  bool? isAdmin;
  String? password;
  List<CartItemModel>? cart;
  String? token;
  List<String>? orders;

  UserModel({this.uid, this.email, this.name, this.isAdmin, this.password, this.cart, this.token, this.orders});

 
  UserModel.fromSnapshot(DocumentSnapshot snapshot) {
    uid = snapshot.id;
    name = snapshot['name'];
    token = snapshot['token'];
    cart = _convertCartItems(snapshot['cart'] ?? []);
    orders = new List<String>.from(snapshot['orders']);
  }

  List<CartItemModel> _convertCartItems(List cartFomDb) {
    List<CartItemModel> _result = [];
    if (cartFomDb.length > 0) {
      cartFomDb.forEach((element) {
        _result.add(CartItemModel.fromMap(element));
      });
    }
    return _result;
  }
}

UtilityController.dart

class UtilityController extends GetxController {
  static UtilityController instance = Get.find();
  Rx<UserModel> userModel = UserModel().obs;

  @override
  void onReady() {
    super.onReady();
    getUserType();
    userModel.bindStream(listenToUser());
  }

  Stream<UserModel> listenToUser() {
    return FirebaseFirestore.instance
        .collection("users")
        .doc(FirebaseAuth.instance.currentUser?.uid)
        .snapshots()
        .map((snapshot) => UserModel.fromSnapshot(snapshot));
  }

OrderController.dart

class OrderController extends GetxController {
  static OrderController instance = Get.find();
  RxList<OrderModel> orders = RxList<OrderModel>([]);

  @override
  void onReady() {
    super.onReady();
    orders.bindStream(getAllOrders());
    ever(utilityController.userModel, function); --> I am using this , but i know this is not the correct way
  }

  function(UserModel userModel) {
    getAllOrders();
  }

  Stream<List<OrderModel>> getAllOrders() {
    return FirebaseFirestore.instance
        .collection("orders")
        .where(FieldPath.documentId, whereIn: utilityController.userModel.value.orders)
        .snapshots()
        .map((query) => query.docs.map((item) => OrderModel.fromMap(item.data(), item.id)).toList());
  }
}

The utilityController.userModel.value.orders is null !!! it's not yet loaded, so all the orders are fetched :( And even if the orders are changed... But new orders are not fetched from the orders collection

How to get over this?


Solution

  • The best approach is to use the worker functions provided by getx controller like:

    • ever - is called every time the Rx variable emits a new value.
    • everAll - Much like ever , but it takes a List of Rx values Called every time its variable is changed. That's it.
    • once - is called only the first time the variable has been changed.