Flutter使用GetX获取Firestore流数据时UI无法自动更新问题求助
问题:GetX绑定Firestore流无法实时更新UI,需切换页面才刷新
我在应用中使用GetX包,它表现良好,但尝试从Firestore获取流数据时,只能获取初始数据却无法实现流更新,UI要等到切换到其他页面再返回才会刷新!每次都必须退出再重新进入才能更新数据,这是个严重的问题。
控制器类代码
class AddSubscriberController extends GetxController { final CollectionReference _subscribersCollectionRef = FirebaseFirestore.instance.collection('Subscribers'); List<SubscriberModel> get subscriberModel => _subscriberModel; final List<SubscriberModel> _subscriberModel = []; RxList<SubscriberModel> subscribers = RxList([]); @override void onInit() { super.onInit(); subscribers.bindStream(getSubscribers()); } Stream<List<SubscriberModel>> getSubscribers() { return _subscribersCollectionRef .orderBy('Register date', descending: false) .snapshots() .map((QuerySnapshot query) { for (var element in query.docs) { subscriberModel.add(SubscriberModel.fromMap(element)); } return subscriberModel; }); } }
UI类代码
Obx(() { AddSubscriberController controller = Get.put(AddSubscriberController()); return ListView.builder( physics: const BouncingScrollPhysics(), shrinkWrap: true, scrollDirection: Axis.vertical, itemCount: controller.subscribers.length, itemBuilder: (context, index) { return buildSubInfo( name: controller.subscribers[index].firstName, lastName: controller.subscribers[index].lastName, father: controller.subscribers[index].father, area: controller.subscribers[index].area, counterNo: controller.subscribers[index].counterNumber, date: controller.subscribers[index].date, ); }, ); }), // Obx
问题根源
- 列表重复累加:每次Firestore推送新快照时,你都在往同一个
_subscriberModel列表里添加数据,没有清空旧数据,导致列表只会越来越长,且新数据无法触发RxList的更新通知。 - 控制器重复实例化:在
Obx内部调用Get.put(),每次UI重建都会重新创建控制器实例,破坏了GetX的单例管理,也会导致流绑定异常。
修复方案
方案一:修正流映射逻辑(推荐)
直接在流的map操作里创建新列表,避免复用旧列表导致的累加问题,同时确保RxList能感知到数据变化:
class AddSubscriberController extends GetxController { final CollectionReference _subscribersCollectionRef = FirebaseFirestore.instance.collection('Subscribers'); RxList<SubscriberModel> subscribers = RxList([]); @override void onInit() { super.onInit(); subscribers.bindStream(getSubscribers()); } Stream<List<SubscriberModel>> getSubscribers() { return _subscribersCollectionRef .orderBy('Register date', descending: false) .snapshots() .map((QuerySnapshot query) { // 每次快照都创建新列表,避免旧数据残留 return query.docs.map((doc) => SubscriberModel.fromMap(doc)).toList(); }); } }
方案二:优化你更新后的监听逻辑
如果你倾向于使用listen而不是bindStream,需要手动更新RxList并触发通知:
class AddSubscriberController extends GetxController { final CollectionReference _subscribersCollectionRef = FirebaseFirestore.instance.collection('Subscribers'); RxList<SubscriberModel> subscribers = RxList([]); @override void onInit() { super.onInit(); getSubscriber(); } void getSubscriber() { _subscribersCollectionRef .orderBy('Register date', descending: true) .snapshots() .listen((event) { subscribers.clear(); // 直接更新RxList,自动触发UI刷新 subscribers.addAll(event.docs.map((doc) => SubscriberModel.fromMap(doc)).toList()); }); } }
UI层必须修正
把Get.put()移到Obx外部,或者在页面初始化时就获取控制器,避免重复实例化:
// 在页面初始化时获取控制器(推荐写法) final AddSubscriberController controller = Get.put(AddSubscriberController()); // 然后在Obx中使用 Obx(() { return ListView.builder( physics: const BouncingScrollPhysics(), shrinkWrap: true, scrollDirection: Axis.vertical, itemCount: controller.subscribers.length, itemBuilder: (context, index) { return buildSubInfo( name: controller.subscribers[index].firstName, lastName: controller.subscribers[index].lastName, father: controller.subscribers[index].father, area: controller.subscribers[index].area, counterNo: controller.subscribers[index].counterNumber, date: controller.subscribers[index].date, ); }, ); }),
内容的提问来源于stack exchange,提问作者Muhammad Qazmouz
相关产品推荐
相关产品推荐

