StreamProvider 和 Firebase

StreamProvider and Firebase

void main() async {
  ...
  final AuthenticationProvider authenticationProvider = AuthenticationProvider();
  await authenticationProvider.initialize();
  runApp(
    MultiProvider(
      providers: [
        Provider<AuthenticationProvider>(create: (_) => authenticationProvider),
        StreamProvider<UserModel>(
          create: (_) => authenticationProvider.currentUser,
          initialData: UserModel(
            id: '',
            email: '',
            displayName: '',
            photo: null,
            premium: false,
            travels: [],
          ),
        )
      ],
      child: MiRoulotte(),
    ),
  );
}

我创建了一个提供程序,它使用当前用户数据生成一个流,当用户注销或登录时,这些数据会发生变化,但数据不会改变。当我注销时,流应该是空的,然后当我登录时,流应该是用户数据。

class AuthenticationProvider {
  Stream<UserModel>? _currentUser;
  Stream<UserModel>? get currentUser => this._currentUser;

  initialize() async {
    ...
    this._currentUser = FirebaseFirestore.instance
      .collection('users')
      .doc(FirebaseAuth.instance.currentUser?.uid)
      .snapshots()
      .map((user) => UserModel.fromJson(user.data() as Map<String, dynamic>));
    ...
  }

  Future signIn({required String email, required String password}) async {
    ...
    this._currentUser = FirebaseFirestore.instance
      .collection('users')
      .doc(userCredential.user?.uid)
      .snapshots()
      .map((user) => UserModel.fromJson(user.data() as Map<String, dynamic>));
    ...
  }


  Future signOut() async {
    ...
    this._currentUser = null;
    ...
  }
}

您实际上并不希望 Stream 成为 null,而是让它发出一个 null 值。 AuthenticationProvider 可以有一个 StreamController,您可以使用它向流中添加当前用户对象的新值。

class AuthenticationProvider {
  final StreamController _controller = SteamController<UserModel?>();
  Stream<UserModel?> get userStream => _controller.stream;

  Future<void> initialize() async {
    final user = // get usermodel from firebase
    _controller.add(user);
  }

  Future<void> signIn({required String email, required String password}) async {
    ...
    final user = // get usermodel from firebase
    _controller.add(user);
  }

  void signOut() {
    _controller.add(null);
  }
}

不要忘记在处理时关闭 StreamController

// in main
Provider<AuthenticationProvider>(
  create: (_) => authenticationProvider,
  dispose: (provider) => provider.dispose(),
),

// in AuthenticationProvider
void dispose() {
  _controller.close();
}