混用GetBuilder()与FutureBuilder()时UI不刷新问题排查
点击解除屏蔽后UI不刷新的原因及修复方案
问题根源
- Future仅初始化一次:你的
userDoc是在控制器onInit阶段调用Firestore的get()方法获取的一次性Future,get()只会拉取一次当前数据,后续后端数据更新后,这个Future存储的仍是旧快照。 - refresh方法未更新数据源:控制器里的
refresh()仅调用update()触发GetBuilder重建,但没有重新请求Firestore的最新数据,因此FutureBuilder拿到的依旧是旧数据,UI自然不会刷新。
修复步骤
1. 修改BlockedAccountController
在refresh方法中重新获取Firestore数据,更新userDoc的引用:
class BlockedAccountController extends GetxController { late Future<DocumentSnapshot<Map<String, dynamic>>> userDoc; // 封装获取数据的方法 void fetchBlockedUsers() { userDoc = FirebaseFirestore.instance .collection("users") .doc(currentusername) .get(); } void refresh() { fetchBlockedUsers(); // 重新拉取最新数据 update(); // 通知GetBuilder重建UI } @override void onInit() { fetchBlockedUsers(); // 初始化时获取数据 super.onInit(); } }
2. 可选优化:改用StreamBuilder实现实时同步
如果希望UI自动响应Firestore数据变化,无需手动调用refresh,可以将Future替换为实时流:
控制器修改
class BlockedAccountController extends GetxController { late Stream<DocumentSnapshot<Map<String, dynamic>>> userStream; void fetchBlockedUsers() { userStream = FirebaseFirestore.instance .collection("users") .doc(currentusername) .snapshots(); // 用snapshots()获取实时数据流 } @override void onInit() { fetchBlockedUsers(); super.onInit(); } }
UI部分替换为StreamBuilder
GetBuilder<BlockedAccountController>( builder: (controller) { return StreamBuilder( stream: controller.userStream, builder: ((context, snapshot) { if (snapshot.hasData && snapshot.data!.exists) { final blockUsers = snapshot.data!["blockusers"] ?? []; return ListView.builder( itemCount: blockUsers.length, shrinkWrap: true, itemBuilder: (context, index) { return Container( color: mainappColor, height: 50, width: double.infinity, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Padding( padding: const EdgeInsets.only(left: 8.0), child: Text( blockUsers[index], style: TextStyle(fontSize: 20), ), ), Padding( padding: const EdgeInsets.only(right: 8.0), child: InkWell( onTap: () async { await unblockAccount(currentusername, blockUsers[index]); // 使用Stream时无需手动refresh,数据会自动同步到UI }, child: Container( decoration: BoxDecoration( color: Colors.purple, borderRadius: BorderRadius.all( Radius.circular(5))), alignment: Alignment.center, width: 80, height: 40, child: Text("unblock".tr), ), ), ) ], ), ); }, ); } else { return Text(""); } })); }, )
内容的提问来源于stack exchange,提问作者BlaCK _ WolF
相关产品推荐
相关产品推荐

