繁体   English   中英

Flutter Riverpod Firebase currentUser Provider 未更新

[英]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.

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