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();
}
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();
}