我正在尝试从 Firestore 中存储的文档中检索数据。我已经尝试了好几次来找到解决此错误的方法,但一直没有找到有用的东西。
这是我的代码。
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class GetUserName extends StatelessWidget {
final String documentId;
GetUserName(this.documentId);
@override
Widget build(BuildContext context) {
CollectionReference users = FirebaseFirestore.instance.collection('Drivers');
return FutureBuilder<DocumentSnapshot>(
future: users.doc(documentId).get(),
builder:
(BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.hasError) {
return Text("Something went wrong");
}
if (snapshot.hasData && !snapshot.data!.exists) {
return Text("Document does not exist");
}
if (snapshot.connectionState == ConnectionState.done) {
Object? data = snapshot.data!.data();
return Text(data!['username']);
}
return Text("loading");
},
);
}
}
当我尝试从数据中检索“用户名”时发生错误。
感谢您的帮助
答案 0 :(得分:3)
问题在于Object
和dynamic
的区别。
在 Dart 中,Object?
是“顶级类型”,这实质上意味着:“所有值都是 Object?
”。
dynamic
通常用于类似的情况(当您不知道正在处理的数据类型,并且不希望类型系统向您抱怨时),但它具有很不一样的意思。简而言之,它的意思是“关闭类型检查,因为我知道我在做什么”。
Object?
和 dynamic
之间的主要区别在于它们的成员。
Object?
上定义了几个成员:
toString()
runtimeType
hashCode
noSuchMethod(Invocation invocation)
所有对象共享这些成员,因为所有对象都是 Object?
。
如果你有一个静态类型 Object?
的值,这些是 Dart 可以保证存在的唯一 4 个成员,所以这些是你唯一被允许调用的(就像你尝试调用时会得到错误一样)致电"some string".notARealMethod()
)。
dynamic
做相反的事情:它假设所有可能的成员都存在,并且从不向您发出任何访问警告,例如:
String s = "hello";
s.notARealMethod(); // compile time error
final d = s as dynamic; // explicitly cast to dynamic
d.notARealMethod(); // now throws at runtime
所以,回到你的代码,你有这个:
Object? data = snapshot.data!.data();
return Text(data!['username']);
data
是一个 Object?
,所以 data!
是一个 Object
,正如我们之前看到的,Object
上仅有的 4 个成员是:{{ 1}}、toString()
、runtimeType
和 hashCode
。所以 Dart 会抱怨,因为它不能保证 noSuchMethod(Invocation invocation)
存在。
要解决此问题:
使用 []
而不是 dynamic
。它不会给你一个编译错误,但如果值最终没有 Object?
运算符,它会在运行时抛出(尽管因为这是来自 firestore,这是一个安全的赌注)
使用类型检查(并使用类型提升):
[]