![](/img/trans.png)
[英]Unable to add post in firestore using react-admin-firebase data provider package
[英]Flutter - Listening for data changes in user profile (Firestore) of Firebase user using provider package
到现在为止,我成功地将我的 Firebase 用户的身份验证更改为 map 并将其更改为我自己的自定义用户 class
import 'package:mypckg/models/user.dart' as local;
import 'package:firebase_auth/firebase_auth.dart' as auth;
import 'package:mypckg/services/database.dart';
class AuthService {
final auth.FirebaseAuth _auth = auth.FirebaseAuth.instance;
// create user obj based on firebase user
Future<local.User> _userFromFirebaseUser(auth.User user) async {
return user != null
? local.User(/* ... init user properties ... */)
: null;
}
// auth change user stream
Stream<local.User> get user {
return _auth.authStateChanges().asyncMap(_userFromFirebaseUser);
}
...
在 Cloud Firestore 中,我存储了该用户的其他值,这些值未被 Firebase 用户覆盖,例如
在main.dart中,提供程序设置为向本地用户提供我的应用程序,以防他登录或注销 (authStateChanges)。 我的想法是订阅另一个 stream,它将监听 Cloud Firestore 中“用户”文档的变化。
class MyPckg extends StatelessWidget {
@override
Widget build(BuildContext context) {
final i18n = I18n.delegate;
//AuthService().signInAnon();
return MultiProvider(
providers: [
StreamProvider<User>(
create: (_) => AuthService().user,
),
/* my idea to subscribe to another stream which will listen to changes on user details in Firestore */
StreamProvider<User>(
create: (_) => AuthService().customUser,
),
],
child: DynamicTheme(
defaultBrightness: Brightness.light,
data: (brightness) {
...
我有一个配置文件视图,用户可以在其中编辑这些值,例如语言环境,它会正确地写入 Firestore
Future<void> updateUserLanguage(String language) async {
return await usersCollection.doc(uid).update({
'language': language,
});
}
但是视图不会重建,因为当前的 stream 仅对 authStateChanges 做出反应。
有没有人有一个工作示例,如何设置来自 Firestore 集合中用户的链接,我的应用程序将监听那里所做的更改? 我的 customUser 方法必须是什么样子?
谢谢!
我决定用 StreamProvider 包装我登录的 state 中的所有内容:
class Wrapper extends StatelessWidget {
@override
Widget build(BuildContext context) {
final user = Provider.of<User>(context);
if (user == null) {
return Authenticate();
} else {
return StreamProvider<Profile>.value(
value: DatabaseService(uid: user.uid).profile,
initialData: Profile(userName: '0', userRole: '0'),
child: HomeScreen(),
);
}
}
}
数据库服务接收 UID 并返回快照:
class DatabaseService {
final String uid;
DatabaseService({
this.uid,
});
static CollectionReference _profileCollection =
FirebaseFirestore.instance.collection('profiles');
Stream<Profile> get profile {
return _profileCollection.doc(uid).snapshots().map(_profileFromSnapshot);
}
Profile _profileFromSnapshot(DocumentSnapshot snapshot) {
return Profile(
userName: snapshot.data()['userName'] ?? '',
userRole: snapshot.data()['role'] ?? '',
);
}
}
最后,我在任何需要的地方通过消费者使用数据:
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: Center(
child: Consumer<Profile>(builder: (
context,
profile,
child,
) {
return Text(profile.userName)
...
编辑:我制作了有关此技术的视频。 链接: https://youtu.be/mAH9YT_y6ec
对于那些也在努力使用这种方法的人,这是我的解决方案(感谢所有引导我采用这种方法的贡献者):
我在 MyClass 中设置了一个方法“setAppUser”,任何孩子都可以调用它。 对此很重要
static _MyClassState? of(BuildContext context) =>
context.findAncestorStateOfType<_MyClassState>();
所以这里是 main.dart(只有必要的部分):
class MyClass extends StatefulWidget {
@override
_MyClassState createState() => _MyClassState();
static _MyClassState? of(BuildContext context) =>
context.findAncestorStateOfType<_MyClassState>();
}
class _MyClassState extends State<MyClass> {
User appUser = User();
set setAppUser(User user) => {
setState(() {
appUser = user;
})
};
@override
Widget build(BuildContext context) {
...
return MultiProvider(
providers: [
StreamProvider<UserLogin>(
initialData: UserLogin(signedIn: false),
create: (_) => AuthService().userAuthStateChanges,
catchError: (_, error) => UserLogin(signedIn: false),
),
StreamProvider<User>(
initialData: appUser,
create: (_) => AuthService().userData,
catchError: (_, error) => appUser,
),
],
child: MaterialApp(
...
在我的登录表单中,在收到我的登录新用户后,我调用了 main.dart 的“setAppUser”方法。 现在小部件被重建,新的 appUser 被设置为我的提供者。
...
await _auth
.signInWithEmailAndPassword(
textControllerEmail.text,
textControllerPassword.text)
.then((result) {
if (result.id != "") {
MyClass.of(context)!.setAppUser = result;
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.