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

Flutter创建Firebase新用户后,如何将默认偏好存储到Cloud Firestore?

问题原因与解决方案

原因

Cloud Firestore仅支持存储原生数据类型(字符串、数字、布尔值、数组、映射、null等),ThemeMode是Dart的枚举类实例,不属于Firestore支持的存储类型,直接写入就会触发「Invalid argument: Instance of 'ThemeMode'」错误。同理FlexScheme作为flexcolorscheme包的枚举类型,也无法直接存储。

正确存储方式

核心思路是将枚举类型转换为Firestore支持的原生类型(推荐用字符串,可读性更强),读取时再转换回枚举实例。

1. 编写枚举与字符串的转换工具函数

// ThemeMode 与字符串互转
String themeModeToString(ThemeMode mode) {
  switch(mode) {
    case ThemeMode.dark:
      return 'dark';
    case ThemeMode.system:
      return 'system';
    default:
      return 'light';
  }
}

ThemeMode stringToThemeMode(String modeStr) {
  switch(modeStr) {
    case 'dark':
      return ThemeMode.dark;
    case 'system':
      return ThemeMode.system;
    default:
      return ThemeMode.light;
  }
}

// FlexScheme 与字符串互转(利用枚举的name属性)
String flexSchemeToString(FlexScheme scheme) => scheme.name;

FlexScheme stringToFlexScheme(String schemeStr) {
  return FlexScheme.values.firstWhere(
    (scheme) => scheme.name == schemeStr,
    orElse: () => FlexScheme.money,
  );
}

2. 改造PrefService的存储与读取逻辑

class PrefService {
  final FirebaseFirestore _firestore = FirebaseFirestore.instance;

  // 创建默认用户偏好
  Future<void> createUserPreferences(String userId) async {
    await _firestore.collection('user_preferences').doc(userId).set({
      'username': 'John Doe',
      'theme_mode': themeModeToString(ThemeMode.light),
      'flex_scheme': flexSchemeToString(FlexScheme.money),
    });
  }

  // 读取并转换回枚举类型
  Future<UserPreferences> getUserPreferences(String userId) async {
    final docSnapshot = await _firestore.collection('user_preferences').doc(userId).get();
    
    if (!docSnapshot.exists) {
      await createUserPreferences(userId);
      return UserPreferences(
        username: 'John Doe',
        themeMode: ThemeMode.light,
        flexScheme: FlexScheme.money,
      );
    }

    final data = docSnapshot.data()!;
    return UserPreferences(
      username: data['username'] as String,
      themeMode: stringToThemeMode(data['theme_mode'] as String),
      flexScheme: stringToFlexScheme(data['flex_scheme'] as String),
    );
  }

  // 更新偏好(示例:更新主题模式)
  Future<void> updateThemeMode(String userId, ThemeMode newMode) async {
    await _firestore.collection('user_preferences').doc(userId).update({
      'theme_mode': themeModeToString(newMode),
    });
  }

  // 更新FlexScheme
  Future<void> updateFlexScheme(String userId, FlexScheme newScheme) async {
    await _firestore.collection('user_preferences').doc(userId).update({
      'flex_scheme': flexSchemeToString(newScheme),
    });
  }
}

// 定义用户偏好模型类
class UserPreferences {
  final String username;
  final ThemeMode themeMode;
  final FlexScheme flexScheme;

  UserPreferences({
    required this.username,
    required this.themeMode,
    required this.flexScheme,
  });
}

3. 在AuthService中关联创建逻辑

在用户创建成功后,调用PrefService生成默认偏好:

class AuthService {
  final FirebaseAuth _auth = FirebaseAuth.instance;
  final PrefService _prefService = PrefService();

  Future<User?> createUser(String email, String password) async {
    try {
      final userCredential = await _auth.createUserWithEmailAndPassword(
        email: email,
        password: password,
      );
      final user = userCredential.user;
      if (user != null) {
        await _prefService.createUserPreferences(user.uid);
      }
      return user;
    } catch (e) {
      print(e);
      return null;
    }
  }
}

4. SettingsScreen中修改偏好

直接调用PrefService的更新方法即可,比如切换主题模式:

// 示例:在SettingsScreen中切换为深色模式
onPressed: () async {
  final userId = FirebaseAuth.instance.currentUser!.uid;
  await PrefService().updateThemeMode(userId, ThemeMode.dark);
},

内容的提问来源于stack exchange,提问作者plotsklapps

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 11:40:35