[英]Flutter Riverpod Firebase currentUser Provider not updated
我是 Flutter 的初学者,state 管理的 Riverpod 和身份验证的 firebase 的初学者。 我希望检索登录用户的 email 以传递到我的 postgres 数据库并检索所有用户信息。 第一次,我只是尝试显示当前用户的昵称。 当我退出应用程序以重新登录时,我遇到了一个问题。身份验证提供程序未更新,因此我从第一个连接的用户那里获取信息。 例如currentUserEmailProvider
仍然获得第一个连接的用户 email。 欢迎任何帮助,我真的被困住了。 我的 auth_repository.dart:
class AuthRepository {
const AuthRepository(this._auth);
final FirebaseAuth _auth;
Stream<User?> get authStateChange => _auth.idTokenChanges();
Stream<User?>get authUserChange => _auth.userChanges();
String? get currentUserEmail => _auth.currentUser?.email;
Future<User?> signInWithEmailAndPassword(
String email, String password) async {
_auth.currentUser?.reload();
try {
final result = await _auth.signInWithEmailAndPassword(
email: email,
password: password,
);
return result.user;
} on FirebaseAuthException catch (e) {
if (e.code == 'user-not-found') {
throw const ErrorHandler(message: 'User not found');
} else if (e.code == 'wrong-password') {
throw const ErrorHandler(message : 'Wrong password');
} else {
throw const ErrorHandler(message: 'An error occurred. Please try again later');
}
}
}
Future<AppUser?> registerWithEmailAndPassword(String email, String password, String nickname, String role, String firstname, String lastname) async {
// Sans ces deux lignes la création d'un nouveau compte entraîne un login automatique sur ce compte
FirebaseApp app = await Firebase.initializeApp(
name: 'Secondary', options: Firebase.app().options);
try {
AppUser? appUser = await UserRepository(email).saveUser(email, nickname, role, firstname, lastname);
if(appUser != null) {
try {
UserCredential result =
await FirebaseAuth.instanceFor(app: app).createUserWithEmailAndPassword(email: email, password: password);
User? user = result.user;
if(user == null) {
throw Exception("user from firebase not found");
}
return appUser;
} on FirebaseException catch(e) {
await UserRepository(email).deleteUser(email);
print(ErrorHandler(message: e.code.toString()));
}
} else {
throw Exception("user from postgres database not found");
}
} on PostgreSQLException catch(e) {
print(ErrorHandler(message: e.code.toString()));
}
return null;
}
Future<void> signOut() async {
await _auth.signOut();
}
}
我的 user_repository.dart:
class UserRepository {
final String email;
PostgreSQLConnection? connection;
UserRepository(this.email){
connection = (connection == null || connection!.isClosed == true
? PostgreSQLConnection(
'10.0.2.2', 5432, DatabaseAccess.databaseName,
queryTimeoutInSeconds: 3600,
timeoutInSeconds: 3600,
username: DatabaseAccess.databaseUser,
password: DatabaseAccess.databasePassword) : connection);
}
}
Future<AppUser?> getCurrentUser(String? currentEmail) async {
print(currentEmail);
try {
await connection!.open();
final result = await connection!.mappedResultsQuery(
'select * from public.user where email = @emailValue',
substitutionValues: {
'emailValue': currentEmail,
},
allowReuse: true,
timeoutInSeconds: 30,
);
final userFromDataBase = result[0]['user']!;
return AppUser(
email: userFromDataBase['email'],
nickname: userFromDataBase['nickname'],
role: userFromDataBase['role'],
firstname: userFromDataBase['firstname'],
lastname: userFromDataBase['lastname'],
);
} on PostgreSQLException catch(e) {
print(ErrorHandler(message: e.toString()));
return null;
}
}
}
我的供应商。dart:
final authRepositoryProvider = Provider<AuthRepository>((ref) {
return AuthRepository(FirebaseAuth.instance);
});
final authStateProvider = StreamProvider<User?>((ref) {
return ref.read(authRepositoryProvider).authStateChange;
});
final currentUserEmailProvider = Provider<String?>((ref) {
return AuthRepository(FirebaseAuth.instance).currentUserEmail;
});
final userRepositoryProvider = Provider.autoDispose<UserRepository>((ref) {
return UserRepository(ref.read(currentUserEmailProvider)!);
});
final futureCurrentUserProvider = Provider<Future<AppUser?>>((ref) {
return ref.read(userRepositoryProvider).getCurrentUser(ref.read(currentUserEmailProvider));
});
final currentUserProvider = FutureProvider.autoDispose<AppUser?>((ref) => ref.read(userRepositoryProvider).getCurrentUser(ref.read(currentUserEmailProvider)));
我的home_screen.dart:
class HomeScreen extends HookConsumerWidget {
const HomeScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final currentUser = ref.watch(currentUserProvider);
return Scaffold(
body: currentUser.when(
data: (user) => _buildBody(context, user, ref),
loading: () => const Center(child: CircularProgressIndicator()),
error: (error, _) => _errorBody(context, ref),
)
);
}
Widget _buildBody(BuildContext context, AppUser? user, WidgetRef ref) {
if(user == null) {
return _errorBody(context, ref);
} else {
return Center(child: Text(
'Welcome ${user.getNickname}',
style: const TextStyle(fontSize: 20),
));
}
}
Widget _errorBody(BuildContext context, WidgetRef ref) {
return const Center(child: Text(
"Error: No user found",
style: TextStyle(fontSize: 20, color: Colors.red),
));
}
}
尝试改变
final currentUserProvider = FutureProvider.autoDispose<AppUser?>((ref) => ref.read(userRepositoryProvider).getCurrentUser(ref.read(currentUserEmailProvider)));
至
final currentUserProvider = FutureProvider.autoDispose<AppUser?>((ref) => ref.read(userRepositoryProvider).getCurrentUser(ref.watch(currentUserEmailProvider)));
和改变
final currentUserEmailProvider = Provider<String?>((ref) {
return AuthRepository(FirebaseAuth.instance).currentUserEmail;
});
至
final currentUserEmailProvider = Provider<String?>((ref) {
return ref.read(authRepositoryProvider).currentUserEmail;
});
好的,我通过以下解决了我的问题。 为了简单起见,我在我的 user_repository.dart 中删除了 singleton。 问题出在我的提供者身上,我找到了一种使用authUserChanges()
方法的方法:
供应商。dart:
final futureCurrentUserProvider = Provider<Future<AppUser?>>((ref) {
return UserRepository().getCurrentUser(ref.watch(emailChangeProvider));
});
final currentUserProvider = FutureProvider.autoDispose<AppUser?>((ref) => UserRepository().getCurrentUser(ref.watch(emailChangeProvider)));
final authChangeProvider = StreamProvider<User?>((ref) {
return ref.read(authRepositoryProvider).authUserChange;
});
final emailChangeProvider = Provider<String?>((ref) {
return ref.watch(authChangeProvider).value?.email;
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.