Flutter+Firebase:如何不查询数据库从本地类获取用户名
问题:无需查询数据库即可获取用户属性的方法?
我有两个页面:
- 注册页面:在此处将用户信息保存至Firebase
- 聊天页面:在此处需要调用用户信息
以下是注册页面的代码片段:
// 调用包含所有Firebase逻辑的类的变量 late final FirebaseCloudStorage _userService; // 创建用户的方法 Future createUserAccount() async { if (_photo == null) return; try { setState(() { _isLoading = true; }); await AuthService.firebase().createUser( email: _email.text, password: _password.text, ); final userId = AuthService.firebase().currentUser?.id; final destination = 'user-profile-image/$userId'; final ref = FirebaseStorage.instance.ref(destination); await ref.putFile(_photo!); imageUrl = await ref.getDownloadURL(); _userService.createNewUser( userId: userId as String, userState: 'new', userImage: imageUrl as String, userFirstName: _userFirstName.text, userLastName: _userLastName.text, userCellNumber: _userCellphoneNumber.text, userCity: _userCity.text, userAreaCode: _userAreaCode.text, userAddress: _userAddress.text, userEmail: _email.text, ); }
包含云用户逻辑的类:
@immutable class CloudUser { final String documentId; final String userId; final String userState; final String userImage; final String userFirstName; final String userLastName; final String userCellNumber; final String userCity; final String userAreaCode; final String userAddress; final String? userEmail; const CloudUser({ required this.documentId, required this.userId, required this.userState, required this.userImage, required this.userFirstName, required this.userLastName, required this.userCellNumber, required this.userCity, required this.userAreaCode, required this.userAddress, required this.userEmail, }); // 我试过调用这个方法但没用! // 我在聊天页面这么调用的:CloudUser.getFirstName() String getFirstName() { return userFirstName; } CloudUser.fromSnapshot(QueryDocumentSnapshot<Map<String, dynamic>> snapshot) : documentId = snapshot.id, userId = snapshot.data()[userIdColumn], userState = snapshot.data()[userStateColumn] ?? "", userImage = snapshot.data()[userImageColumn] ?? "", userFirstName = snapshot.data()[userFirstNameColumn] ?? "", userLastName = snapshot.data()[jobAreaCodeColumn] ?? "", userCellNumber = snapshot.data()[userCellNumberColumn] ?? "", userCity = snapshot.data()[userCityColumn] ?? "", userAreaCode = snapshot.data()[userAreaCodeColumn] ?? "", userAddress = snapshot.data()[userAddressColumn] ?? "", userEmail = snapshot.data()[userEmailColumn] ?? ""; }
与FirebaseCloudStorage交互的逻辑类:
class FirebaseCloudStorage { final user = FirebaseFirestore.instance.collection('user'); Future<CloudUser> createNewUser({ required String userId, required String userState, required String userImage, required String userFirstName, required String userLastName, required String userCellNumber, required String userCity, required String userAreaCode, required String userAddress, required String userEmail, }) async { final document = await user.add({ userIdColumn: userId, userStateColumn: userState, userImageColumn: userImage, userFirstNameColumn: userFirstName, userLastNameColumn: userLastName, userCellNumberColumn: userCellNumber, userCityColumn: userCity, userAreaCodeColumn: userAreaCode, userAddressColumn: userAddress, userEmailColumn: userEmail, }); final fetchedUser = await document.get(); return CloudUser( documentId: fetchedUser.id, userId: userId, userState: userState, userImage: userImage, userFirstName: userFirstName, userLastName: userLastName, userCellNumber: userCellNumber, userCity: userCity, userAreaCode: userAreaCode, userAddress: userAddress, userEmail: userEmail, ); } // 我可以加个方法用用户ID从服务器获取数据,但我觉得没必要这么做 // 单例模式 static final FirebaseCloudStorage _shared = FirebaseCloudStorage._sharedInstance(); FirebaseCloudStorage._sharedInstance(); factory FirebaseCloudStorage() => _shared; }
有没有高效存储和检索这些数据的方法?
解决方案
1. 本地缓存用户信息(无需重复查库)
注册成功后,把CloudUser实例转成JSON格式保存到本地缓存(比如shared_preferences),聊天页面直接从缓存读取即可:
实现步骤:
- 添加依赖:
shared_preferences: ^2.2.2(根据实际版本调整) - 注册成功后存入缓存:
// 在createUserAccount方法中,调用完_userService.createNewUser后 final newUser = await _userService.createNewUser( // 传入注册时的参数 ); // 将CloudUser转为JSON final userJson = { 'documentId': newUser.documentId, 'userId': newUser.userId, 'userState': newUser.userState, 'userImage': newUser.userImage, 'userFirstName': newUser.userFirstName, 'userLastName': newUser.userLastName, 'userCellNumber': newUser.userCellNumber, 'userCity': newUser.userCity, 'userAreaCode': newUser.userAreaCode, 'userAddress': newUser.userAddress, 'userEmail': newUser.userEmail, }; // 存入SharedPreferences final prefs = await SharedPreferences.getInstance(); await prefs.setString('current_user', jsonEncode(userJson));
- 聊天页面读取缓存:
// 在聊天页面初始化时执行 final prefs = await SharedPreferences.getInstance(); final userJsonString = prefs.getString('current_user'); if (userJsonString != null) { final userJson = jsonDecode(userJsonString); final currentUser = CloudUser( documentId: userJson['documentId'], userId: userJson['userId'], userState: userJson['userState'], userImage: userJson['userImage'], userFirstName: userJson['userFirstName'], userLastName: userJson['userLastName'], userCellNumber: userJson['userCellNumber'], userCity: userJson['userCity'], userAreaCode: userJson['userAreaCode'], userAddress: userJson['userAddress'], userEmail: userJson['userEmail'], ); // 现在可以正常调用currentUser.getFirstName() }
2. 利用Firebase Auth自定义Claims(适合少量关键属性)
如果只需要少量核心属性(比如名字、头像URL),可以把这些信息存到Firebase Auth的自定义Claims中,无需查询Firestore,直接通过Auth实例获取:
实现步骤:
- 注册成功后设置自定义Claims:
// 在createUserAccount中,获取userId后执行 await FirebaseAuth.instance.currentUser?.updateClaims({ 'firstName': _userFirstName.text, 'lastName': _userLastName.text, 'imageUrl': imageUrl, });
- 聊天页面获取属性:
final user = FirebaseAuth.instance.currentUser; if (user != null) { await user.reload(); // 确保获取最新的Claims final firstName = user.claims?['firstName'] as String?; final imageUrl = user.claims?['imageUrl'] as String?; // 直接使用这些属性 }
注意:自定义Claims适合存储少量、不敏感、不频繁变更的信息,更新Claims需要后端权限(或Firebase Functions),且客户端需调用reload才能获取最新值。
3. 全局状态管理(Provider/GetX/Bloc)
用状态管理工具将用户信息存入全局状态,注册成功后更新状态,聊天页面直接从全局状态读取:
以GetX为例:
- 创建UserController:
class UserController extends GetxController { var currentUser = Rxn<CloudUser>(); void setUser(CloudUser user) { currentUser.value = user; } }
- 注册页面设置全局用户:
final newUser = await _userService.createNewUser(...); Get.put(UserController()).setUser(newUser);
- 聊天页面获取用户:
final user = Get.find<UserController>().currentUser.value; if (user != null) { print(user.getFirstName()); }
补充说明
你之前调用CloudUser.getFirstName()失败,是因为getFirstName()是实例方法,必须先创建CloudUser的实例才能调用,不能直接用类名调用。
内容的提问来源于stack exchange,提问作者user17281101
相关产品推荐
相关产品推荐

