在我的应用程序中,我有以下的提供者。
@override
Widget build(BuildContext context) {
return OverlaySupport.global(
child: MultiProvider(
providers: [userLoggedIn, currentUserData],
child: MaterialApp(...)))
} var userLoggedIn = StreamProvider<User?>.value(
value: FirebaseAuth.instance.authStateChanges(), initialData: null);
var currentUserData = StreamProvider<FrediUser>.value(
updateShouldNotify: (_, __) => true,
initialData: FrediUser(
loginProvider: '',
email: '',
admin: false,
profileSettings: [],
profileChips: [],
profileStats: [],
id: 'loading',
imageUrl: 'loading',
bio: 'loading',
username: 'loading'),
value: currentUserID != null ? currentUserDataStream() : null,
);问题
当用户注销(或首次登录)时,提供程序是:
包含旧用户数据的
我想做的是,一旦有了新用户,就重新刷新或调用Stream Providers,或者在用户注销后删除所有数据。
谢谢!
发布于 2022-04-21 00:30:38
你可以听到这样的状态变化。
FirebaseAuth.instance
.authStateChanges()
.listen((User? user) {
if (user == null) {
print('User is currently signed out!');
} else {
print('User is signed in!');
}
});发布于 2022-04-21 11:00:52
我一直面临着与您类似的问题,我想出了一个解决方案--尽管不确定它是否符合Provider体系结构。
问题
我有一个DatabaseService类,它有一个类型为Stream<CustomUser>函数的流函数,我使用它的方式如下:
//--- main.dart ---//
runApp(MultiProvider(
providers: [
// ..some other providers.. //
// data provider
Provider<DatabaseService?>(
create: (_) => databaseService,
),
// data provider
StreamProvider<CustomUser?>(
create: (context) => databaseService.getCurrUserFromDb(),
lazy: false,
initialData: null,
updateShouldNotify: (_, __) => true,
),
],
child: MyApp(
initPage: initPage,
)
));流功能:
//--- database_service.dart ---//
// gets the user from database and
// assigns it to the variable _user.
Stream<CustomUser?> getCurrUserFromDB() async* {
try {
CustomUser? currUser;
if (_user != null) {
await for (DocumentSnapshot<Object?> event
in users.doc(user.uid).snapshots()) {
final jsonMap = event.data() as Map<String, dynamic>;
currUser = CustomUser.fromJson(jsonMap);
_user = currUser;
CustomPreferences.setCurrUser(_user);
yield currUser;
}
}
} catch (e) {
rethrow;
}
}databaseService是带有命名构造函数的DatabaseService类。
这是而不是在开始时或流具有新值时导致小部件重建的结果。
解决方案:
在StreamController类中创建了一个DatabaseService,当用户在其中签名时,我向StreamController添加了一个getCurrUserFromDB()函数,如下所示
//--- authentication_screen.dart ---//
...
ElevatedButton(
child: const Text("Sign In"),
onPressed: () async {
final user = await AuthService().googleSignIn();
if (user != null) {
final dbProvider = context.read<DatabaseService?>();
await dbProvider?.setInitUser(user, context);
await dbProvider?.cusUserController
.addStream(dbProvider.getCurrUserFromDB());
}
}),
...使用setInitUser(CustomUser? user)设置DatabaseService中_user变量的值,并使用user获取该变量。
推理
我正在在应用程序的开头创建a StreamProvider,它的源代码StreamController需要有一个流来听,所以我在尝试登录时给出了它。
甚至更简单的解决方案是在DatabaseService类的构造函数中这样做:
//--- database_service.dart ---//
// method to add the stream to controller //
Future<void> addStream() async {
if (!_cusUserController.isClosed && !_cusUserController.isPaused) {
await _cusUserController.addStream(getCurrUserFromDB());
}
}
// constructor //
DatabaseService._init(CustomUser cusUser) {
addStream();
_user = cusUser;
}最后要注意的一点是,我没有将Controller声明为final。当我宣布它为final时,流没有更新,所以现在看起来是这样的:
//--- database_service.dart ---//
StreamController<CustomUser?> _cusUserController = StreamController();TL;DR
我创建了一个StreamProvider,它在它的create属性中返回一个StreamController,然后在应用程序的生命周期内使用addStream方法给控制器一个流。
对不起,我只是想尽可能清楚地说出来。
https://stackoverflow.com/questions/71891401
复制相似问题