如何使用颤振和飞镖从 Cloud Firestore 检索特定数据?
Posted
技术标签:
【中文标题】如何使用颤振和飞镖从 Cloud Firestore 检索特定数据?【英文标题】:how to retrieve specific data from Cloud Firestore using flutter and dart? 【发布时间】:2020-05-12 20:29:36 【问题描述】:我一直在阅读 *** 阅读相关的帖子。但是,我还没有找到一个简单的解决方案,对于像我这样的初学者来说很容易理解。目前,我的 Cloud Firestore 数据库如下所示:
在用户输入足够的信息以填充文档中的每个字段后(ID 是通过电话身份验证的经过身份验证的用户的 UID),然后将其发送到数据库中。之后,用户被重定向到应该显示这些字段中的每一个的主屏幕。这就是我卡住的地方。下面是一个我已经开始实现的方法,它将返回一个字符串,该字符串将位于 Text 小部件中,以显示在数据库中找到的用户名。
String getUsername(FirebaseUser user, Firestore firestore)
//get the document reference
DocumentReference docReference = firestore.document("Users/" + user.uid);
Future<DocumentSnapshot> snapshot = docReference.get();
Stream<DocumentSnapshot> stream = snapshot.asStream();
//stub to ignore compiler warnings
return null;
如您所见,在使用 Futures 和 Streams 时,我相当迷茫。我在 youtube 上观看了 google flutter 开发人员的视频,他们帮助我达到了这一点。我还尝试使用 Future 对象提供的 then() 和 whenCompleted() 方法,但是我发现自己挖了一个越来越大的洞。
非常感谢所有帮助!
【问题讨论】:
这个“futures, async, await”文档是一个很好的起点:dart.dev/codelabs/async-await#what-is-a-future 此外,这个关于异步代码的简短视频提供了一个很好的概述:youtube.com/watch?v=nHsxIQ9KMn0 祝你好运! 【参考方案1】:要获取用户信息,请尝试以下操作:
Future<DocumentSnapshot> getUserInfo()async
var firebaseUser = await FirebaseAuth.instance.currentUser();
return await Firestore.instance.collection("users").document(firebaseUser.uid).get();
然后在您的build()
方法中使用FutureBuilder
:
FutureBuilder(
future: getUserInfo(),
builder: (context, AsyncSnapshot<DocumentSnapshot> snapshot)
if (snapshot.connectionState == ConnectionState.done)
return ListView.builder(
shrinkWrap: true,
itemCount: 1,
itemBuilder: (BuildContext context, int index)
return ListTile(
title:
Text(snapshot.data.data["email"]),
);
);
else if (snapshot.connectionState == ConnectionState.none)
return Text("No data");
return CircularProgressIndicator();
,
),
在方法中使用await
时,该方法需要声明为async
。此外,您需要返回一个Future
,以便能够在屏幕上显示结果,然后您需要使用FutureBuilder
小部件。
https://dart.dev/codelabs/async-await
【讨论】:
【参考方案2】:当您只需要获取一次数据时,您可以使用 Futures,例如:
final queryofdocs = await Firestore.instance.collection('Users').getDocuments()
此代码返回一个Future<QuerySnapshot>
,其中包含该集合中的所有文档。
然后你可以尝试像这样获取一个文档:
final queryofonedocs = await Firestore.instance.document('users/uid').get()
这会返回一个Future<DocumentSnapshot>
,其中包含该文档中的所有字段。
最后,您可以使用 Streams 监听数据变化。
final suscription = await Firestore.instance.collection('tasks').snapshots()
如果您更改某些数据并取消存储应用更新中的数据,这将返回 Stream<QuerySnapshot>
。
DocumentSnapshots
在文档中有信息字段,QuerySnapshot
是 DocumentSnapshots
的集合。
希望对你有帮助
【讨论】:
【参考方案3】:以下代码是null safe,并已更新为最新版本的库:
var collection = FirebaseFirestore.instance.collection('users');
FutureBuilder<DocumentSnapshot<Map<String, dynamic>>>(
future: collection.doc('$user.uid').get(),
builder: (_, snapshot)
if (snapshot.hasError) return Text('Error = $snapshot.error');
if (snapshot.hasData)
var output = snapshot.data!.data();
var value = output!['email']; // example@gmail.com
return Text(value);
return Center(child: CircularProgressIndicator());
,
);
【讨论】:
@Kamlesh 你需要使用我自己还没有尝试过的rxdart
包。
谢谢亲爱的@CopsOnRoad,我已经用过它了,但可能有些东西不见了或还没用。
@Kamlesh 不幸的是,我对此无能为力。对不起:(【参考方案4】:
这是我们如何做到这一点的过程
创建 AuthController 类
class AuthController extends GetxController
static AuthController to = Get.find();
AppLocalizations_Labels labels;
TextEditingController nameController = TextEditingController();
TextEditingController emailController = TextEditingController();
TextEditingController passwordController = TextEditingController();
final FirebaseAuth _auth = FirebaseAuth.instance;
final FirebaseFirestore _db = FirebaseFirestore.instance;
Rx<User> firebaseUser = Rx<User>();
Rx<UserModel> firestoreUser = Rx<UserModel>();
final RxBool admin = false.obs;
@override
void onReady() async
//run every time auth state changes
firebaseUser.value = await getUser;
firebaseUser.bindStream(user);
super.onReady();
@override
void onClose()
nameController?.dispose();
emailController?.dispose();
passwordController?.dispose();
super.onClose();
// Firebase user one-time fetch
Future<User> get getUser async => _auth.currentUser;
// Firebase user a realtime stream
Stream<User> get user => _auth.authStateChanges();
//Streams the firestore user from the firestore collection
Stream<UserModel> streamFirestoreUser()
print('streamFirestoreUser()');
if (firebaseUser?.value?.uid != null)
return _db
.doc('/users/$firebaseUser.value.uid')
.snapshots()
.map((snapshot) => UserModel.fromMap(snapshot.data()));
return null;
//get the firestore user from the firestore collection
Future<UserModel> getFirestoreUser()
if (firebaseUser?.value?.uid != null)
return _db.doc('/users/$firebaseUser.value.uid').get().then(
(documentSnapshot) => UserModel.fromMap(documentSnapshot.data()));
return null;
//Method to handle user sign in using email and password
signInWithEmailAndPassword(BuildContext context) async
final labels = AppLocalizations.of(context);
showLoadingIndicator();
try
await _auth.signInWithEmailAndPassword(
email: emailController.text.trim(),
password: passwordController.text.trim()
);
emailController.clear();
passwordController.clear();
hideLoadingIndicator();
catch (error)
hideLoadingIndicator();
Get.snackbar(labels.auth.signInErrorTitle, labels.auth.signInError,
snackPosition: SnackPosition.BOTTOM,
duration: Duration(seconds: 7),
backgroundColor: Get.theme.snackBarTheme.backgroundColor,
colorText: Get.theme.snackBarTheme.actionTextColor);
创建 userInfo 类,通过 GetBuilder 显示用户数据
class UserInfo extends StatelessWidget
@override
Widget build(BuildContext context)
final labels = AppLocalizations.of(context);
return GetBuilder<AuthController>(
init: AuthController(),
builder: (controller) => controller?.firestoreUser?.value?.uid == null
? Center(
child: CircularProgressIndicator(),
)
: Scaffold(
appBar: AppBar(
title: Text(labels?.home?.title),
actions: [
IconButton(
icon: Icon(Icons.settings),
onPressed: ()
Get.to(SettingsUI());
),
],
),
body: Center(
child: Column(
children: <Widget>[
SizedBox(height: 120),
Avatar(controller.firestoreUser.value),
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
FormVerticalSpace(),
Text(
labels.home.uidLabel +
': ' +
controller.firestoreUser.value.uid,
style: TextStyle(fontSize: 16)),
FormVerticalSpace(),
Text(
labels.home.nameLabel +
': ' +
controller.firestoreUser.value.name,
style: TextStyle(fontSize: 16)),
FormVerticalSpace(),
Text(
labels.home.emailLabel +
': ' +
controller.firestoreUser.value.email,
style: TextStyle(fontSize: 16)),
FormVerticalSpace(),
Text(
labels.home.adminUserLabel +
': ' +
controller.admin.value.toString(),
style: TextStyle(fontSize: 16)),
],
),
],
),
),
),
);
【讨论】:
以上是关于如何使用颤振和飞镖从 Cloud Firestore 检索特定数据?的主要内容,如果未能解决你的问题,请参考以下文章