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
相关产品推荐
相关产品推荐

