You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 06:42:06