简体   繁体   English

Flutter Riverpod Firebase currentUser Provider 未更新

[英]Flutter Riverpod Firebase currentUser Provider not updated

I'm beginner in Flutter, Riverpod for the state management and firebase for the authentication.我是 Flutter 的初学者,state 管理的 Riverpod 和身份验证的 firebase 的初学者。 I'm looking to retrieve the logged user's email to pass to my postgres database and retrieve all the user information.我希望检索登录用户的 email 以传递到我的 postgres 数据库并检索所有用户信息。 In a first time, I just try to display the nickname of the current user.第一次,我只是尝试显示当前用户的昵称。 I am facing a problem when I log out of the app to log back in. The auth providers are not updated so I get informations from the very first connected user.当我退出应用程序以重新登录时,我遇到了一个问题。身份验证提供程序未更新,因此我从第一个连接的用户那里获取信息。 For example currentUserEmailProvider still get the first connected user email.例如currentUserEmailProvider仍然获得第一个连接的用户 email。 Any help is welcome, I'm really stuck.欢迎任何帮助,我真的被困住了。 My auth_repository.dart:我的 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();
  }
}

My user_repository.dart:我的 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;
    }
  }
}

My providers.dart:我的供应商。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)));

My home_screen.dart:我的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),
    ));
  }

}

Try changing尝试改变

final currentUserProvider = FutureProvider.autoDispose<AppUser?>((ref) => ref.read(userRepositoryProvider).getCurrentUser(ref.read(currentUserEmailProvider)));

to

final currentUserProvider = FutureProvider.autoDispose<AppUser?>((ref) => ref.read(userRepositoryProvider).getCurrentUser(ref.watch(currentUserEmailProvider)));

and changing和改变

final currentUserEmailProvider = Provider<String?>((ref) {
  return AuthRepository(FirebaseAuth.instance).currentUserEmail;
});

to

final currentUserEmailProvider = Provider<String?>((ref) {
  return ref.read(authRepositoryProvider).currentUserEmail;
});

Ok I resolved my problem with this following.好的,我通过以下解决了我的问题。 To be simplier I removed the singleton in my user_repository.dart.为了简单起见,我在我的 user_repository.dart 中删除了 singleton。 The problem was from my providers and I found a way to use the authUserChanges() method:问题出在我的提供者身上,我找到了一种使用authUserChanges()方法的方法:

providers.dart:供应商。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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM