Flutter中如何将RxBool变量默认值设为Firebase用户数据
问题:如何将RxBool变量
RxBool isVegan = false.obs;的默认值从false改为使用Firebase中的用户对应值? 以下是我的preferences_controller.dart代码:
class PreferencesController extends GetxController { static PreferencesController get instance => Get.find(); final userController = UserController.instance; final userRepository = Get.put(UserRepository()); RxBool isVegan = false.obs; RxBool isDairyFree = false.obs; GlobalKey<FormState> updateVeganFormKey = GlobalKey<FormState>(); GlobalKey<FormState> updateDairyFormKey = GlobalKey<FormState>(); // 页面加载时初始化用户数据 @override void onInit() { initializePreferences(); super.onInit(); } // 获取用户记录 Future<void> initializePreferences() async { isVegan.value = userController.user.value.preferences['Diet']['IsVegan'] ?? false; isDairyFree.value = userController.user.value.preferences['Diet']['IsDairyFree'] ?? false; void saveVegan(bool? value) { isVegan.value = value ?? false; } void saveDairy(bool? value) { isDairyFree.value = value ?? false; } Future<void> updatePreferences(int redirect) async { try { // 根据redirect值跳转对应页面 switch (redirect) { case 0: // 表单验证 if (!updateVeganFormKey.currentState!.validate()) { updateVeganFormKey.currentState!.save(); return; } if (!updateDairyFormKey.currentState!.validate()) { updateDairyFormKey.currentState!.save(); return; } Map<String, dynamic> Diet = { 'Diet': { 'IsVegan': isVegan.value, 'IsDairyFree': isDairyFree.value, }, }; // 更新Diet映射中的isVegan字段 Diet['Diet']['IsVegan'] = isVegan.value; Diet['Diet']['IsDairyFree'] = isDairyFree.value; // 构建Firestore更新数据 Map<String, dynamic> dietData = { 'Preferences': { 'Allergy': { 'IsEgg': userController.user.value.preferences['Allergy'] ?['IsEgg'], 'IsNut': userController.user.value.preferences['Allergy'] ?['IsNut'], }, 'Diet': { 'IsVegan': isVegan.value, 'IsDairyFree': isDairyFree.value, }, }, }; await userRepository.updateSingleField(dietData); // 更新Rx用户数据 userController.user.value.preferences['IsVegan'] = isVegan.value; userController.user.update((user) { user?.preferences['Diet'] ??= {}; user?.preferences['Diet']['IsVegan'] = isVegan.value; }); userController.user.value.preferences['IsDairyFree'] = isDairyFree.value; userController.user.update((user) { user?.preferences['Diet'] ??= {}; user?.preferences['Diet']['IsDairyFree'] = isDairyFree.value; }); Get.off(() => const AllergyConfigurationScreen(), transition: Transition.rightToLeftWithFade); break; // 剩余代码 }
Firestore数据库结构:
用户文档下包含
Preferences字段,Preferences下嵌套Diet子字段,Diet中包含IsVegan和IsDairyFree两个布尔类型字段。
解决方案
1. 修复初始化逻辑的空值安全问题
原代码直接链式访问userController.user.value.preferences['Diet']['IsVegan']存在空指针风险,若preferences或Diet为null会直接抛出异常,需逐层做空值校验:
Future<void> initializePreferences() async { // 先确保用户数据已从Firebase加载完成(需确保userController有对应的加载方法,比如fetchUser) await userController.fetchUser(); final user = userController.user.value; final preferences = user.preferences; final diet = preferences?['Diet'] as Map<String, dynamic>?; isVegan.value = diet?['IsVegan'] ?? false; isDairyFree.value = diet?['IsDairyFree'] ?? false; }
2. 监听用户数据变化,实时同步偏好值
如果后续用户数据有更新,可通过监听自动同步isVegan的值,在onInit中添加监听逻辑:
@override void onInit() { super.onInit(); // 监听用户数据变化,实时更新偏好设置 ever(userController.user, (User user) { final diet = user.preferences?['Diet'] as Map<String, dynamic>?; isVegan.value = diet?['IsVegan'] ?? false; isDairyFree.value = diet?['IsDairyFree'] ?? false; }); initializePreferences(); }
3. 简化更新逻辑中的冗余代码
原updatePreferences方法存在重复赋值和错误直接修改user.value的问题,优化后代码更简洁:
Future<void> updatePreferences(int redirect) async { try { switch (redirect) { case 0: if (!updateVeganFormKey.currentState!.validate()) { updateVeganFormKey.currentState!.save(); return; } if (!updateDairyFormKey.currentState!.validate()) { updateDairyFormKey.currentState!.save(); return; } // 直接构建Firestore更新数据,移除冗余代码 final dietData = { 'Preferences': { 'Allergy': { 'IsEgg': userController.user.value.preferences?['Allergy']?['IsEgg'], 'IsNut': userController.user.value.preferences?['Allergy']?['IsNut'], }, 'Diet': { 'IsVegan': isVegan.value, 'IsDairyFree': isDairyFree.value, }, }, }; await userRepository.updateSingleField(dietData); // 统一更新userController中的用户数据,避免重复操作 userController.user.update((user) { user?.preferences ??= {}; user?.preferences['Diet'] ??= {}; user?.preferences['Diet']['IsVegan'] = isVegan.value; user?.preferences['Diet']['IsDairyFree'] = isDairyFree.value; }); Get.off(() => const AllergyConfigurationScreen(), transition: Transition.rightToLeftWithFade); break; // 剩余代码 }
内容的提问来源于stack exchange,提问作者Safwan Norasidin
相关产品推荐
相关产品推荐

