[英]Error: The method 'data' isn't defined for the class 'Object?'
Error: The method 'data' isn't defined for the class 'Object?'.
- 'Object' is from 'dart:core'.
Try correcting the name to the name of an existing method, or defining a method named 'data'.
Map _productMap = productSnap.data.data();
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:your_store/screens/product_page.dart';
import 'package:your_store/services/firebase_services.dart';
import 'package:your_store/widgets/custom_action_bar.dart';
class SavedTab extends StatelessWidget {
final FirebaseServices _firebaseServices = FirebaseServices();
@override
Widget build(BuildContext context) {
return Container(
child: Stack(
children: [
FutureBuilder<QuerySnapshot>(
future: _firebaseServices.usersRef
.doc(_firebaseServices.getUserId())
.collection("Saved")
.get(),
builder: (context, snapshot) {
if (snapshot.hasError) {
return Scaffold(
body: Center(
child: Text("Error: ${snapshot.error}"),
),
);
}
// Collection Data ready to display
if (snapshot.connectionState == ConnectionState.done) {
// Display the data inside a list view
return ListView(
padding: EdgeInsets.only(
top: 108.0,
bottom: 12.0,
),
children: snapshot.data!.docs.map((document) {
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ProductPage(
productId: document.id,
),
));
},
child: FutureBuilder(
future:
_firebaseServices.productRef.doc(document.id).get(),
builder: (context, productSnap) {
if (productSnap.hasError) {
return Container(
child: Center(
child: Text("${productSnap.error}"),
),
);
}
if (productSnap.connectionState ==
ConnectionState.done) {
Map _productMap = productSnap.data.data();
return Padding(
padding: const EdgeInsets.symmetric(
vertical: 16.0,
horizontal: 24.0,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
width: 90,
height: 90,
child: ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child: Image.network(
"${_productMap['images'][0]}",
fit: BoxFit.cover,
),
),
),
Container(
padding: EdgeInsets.only(
left: 16.0,
),
child: Column(
mainAxisAlignment:
MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
"${_productMap['name']}",
style: TextStyle(
fontSize: 18.0,
color: Colors.black,
fontWeight: FontWeight.w600),
),
Padding(
padding: const EdgeInsets.symmetric(
vertical: 4.0,
),
child: Text(
"\$${_productMap['price']}",
style: TextStyle(
fontSize: 16.0,
color: Theme.of(context)
.accentColor,
fontWeight: FontWeight.w600),
),
),
Text(
"Size - ${document['size']}",
style: TextStyle(
fontSize: 16.0,
color: Colors.black,
fontWeight: FontWeight.w600),
),
],
),
),
],
),
);
}
return Container(
child: Center(
child: CircularProgressIndicator(),
),
);
},
),
);
}).toList(),
);
}
// Loading State
return Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
},
),
CustomActionBar(
title: "Saved",
hasBackArrow: false,
),
],
),
);
}
}
There are multiple problems in your code (taken from your GitHub repo.).您的代码中存在多个问题(取自您的 GitHub 存储库。)。 I will try list all the problems here with some explanation about each.
我将尝试在这里列出所有问题,并对每个问题进行一些解释。 A common theme are a misunderstanding of using generics so I will recommend you to read about them:
一个常见的主题是对使用泛型的误解,所以我建议你阅读它们:
https://dart.dev/guides/language/language-tour#generics https://dart.dev/guides/language/language-tour#generics
I will highly recommend you are trying to be as specific as possible with all your types in your code since a lot of the current behavior are making use of dynamic
which is not really needed.我强烈建议您尝试对代码中的所有类型尽可能具体,因为当前的许多行为都在使用并非真正需要的
dynamic
。 By making the code more statically type safe, you can also get the compiler to find a lot of errors which is otherwise going to be runtime crashes.通过使代码更加静态类型安全,您还可以让编译器发现很多错误,否则这些错误将导致运行时崩溃。
The following found problems is not a full list since most of your problems has the same underlying problem as one of these.以下发现的问题不是完整列表,因为您的大多数问题与其中一个具有相同的潜在问题。
In firebase_services.dart
you has this:在
firebase_services.dart
你有这个:
final CollectionReference productRef =
FirebaseFirestore.instance.collection("Products");
final CollectionReference usersRef =
FirebaseFirestore.instance.collection("Users");
This is not correct since you are removing the generic type from CollectionReference
so it becomes CollectionReference<dynamic>
.这是不正确的,因为您正在从
CollectionReference
中删除泛型类型,因此它变为CollectionReference<dynamic>
。 If you read the return type of .collection
in both cases you will see the returned type is CollectionReference<Map<String, dynamic>>
.如果您在两种情况下阅读
.collection
的返回类型,您将看到返回的类型是CollectionReference<Map<String, dynamic>>
。
This is important since this type is used when calling methods on the CollectionReference
object other places in your program.这很重要,因为在程序中的其他位置调用
CollectionReference
对象上的方法时会使用此类型。
So this should be changed to:所以这应该改为:
final CollectionReference<Map<String, dynamic>> productRef =
FirebaseFirestore.instance.collection("Products");
final CollectionReference<Map<String, dynamic>> usersRef =
FirebaseFirestore.instance.collection("Users");
FutureBuilder
FutureBuilder
缺少泛型In cart_page.dart
you have a line 52 the following:在
cart_page.dart
,第52 行如下:
child: FutureBuilder(
future:
_firebaseServices.productRef.doc(document.id).get(),
builder: (context, productSnap) {
If you check the resolved type of productSnap
you can see Dart thinks this has the type AsyncSnapshot<Object?>
which is not that specific.如果您检查
productSnap
的已解析类型,您可以看到 Dart 认为它具有AsyncSnapshot<Object?>
类型, AsyncSnapshot<Object?>
不是那么具体。 If you look at the documentation for FutureBuilder
it shows you should use this with a generic type which tells what type you expect the Future
to return:如果您查看
FutureBuilder
的文档,它会显示您应该将其与泛型类型一起使用,该类型告诉您期望Future
返回的类型:
https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html
So change the definition of FutureBuilder
to:因此将
FutureBuilder
的定义更改为:
child: FutureBuilder<DocumentSnapshot<Map<String, dynamic>>>(
Another example is in the same file at line 20 with:另一个例子是在同一个文件的第 20 行:
FutureBuilder<QuerySnapshot>(
future: _firebaseServices.usersRef
.doc(_firebaseServices.getUserId())
.collection("Cart")
.get(),
builder: (context, snapshot) {
Here, you have QuerySnapshot
but forgets that it also takes generic arguments.在这里,您有
QuerySnapshot
但忘记了它也需要通用参数。 So based on the returned value from the future
segment this should really be:因此,根据
future
段的返回值,这应该是:
FutureBuilder<QuerySnapshot<Map<String, dynamic>>>(
With our more specific types in the code we come to this error (still in cart_page.dart
) which gives us an error:随着代码中更具体的类型,我们遇到了这个错误(仍在
cart_page.dart
),这给了我们一个错误:
if (productSnap.connectionState ==
ConnectionState.done) {
Map _productMap = productSnap.data.data();
A value of type 'Map<String, dynamic>?'
'Map<String, dynamic>?' 类型的值can't be assigned to a variable of type 'Map<dynamic, dynamic>'.
不能分配给类型为“Map<dynamic, dynamic>”的变量。
The problem here is that by writing Map
you are actually writing Map<dynamic, dynamic>
which will remove important type information.这里的问题是,通过编写
Map
您实际上是在编写Map<dynamic, dynamic>
,这将删除重要的类型信息。 I will recommend just using var
or final
and let Dart automatically assign the best possible type for the variable:我建议只使用
var
或final
并让 Dart 自动为变量分配最佳类型:
final _productMap = productSnap.data.data();
null
valuenull
值的处理Let's continue with the exact same line.让我们继续完全相同的行。 Now we gets the following error:
现在我们得到以下错误:
The method 'data' can't be unconditionally invoked because the receiver can be 'null'.
方法 'data' 不能无条件调用,因为接收者可以为 'null'。
The problem is that the data
property can be null
in case of an error has happen.问题是如果发生错误,
data
属性可以为null
。 I don't know how you want to handle this so for now, I am just going to ignore the problem and uses !
我不知道您想如何处理这个问题,所以现在,我将忽略该问题并使用
!
to force a runtime null-check to be added:强制添加运行时空检查:
final _productMap = productSnap.data!.data();
But this is not enough since the output from data()
can also be null
which your code are not handling.但这还不够,因为
data()
的输出也可以是您的代码null
。 Again, I don't know how you want to handle empty data so I am just ignoring the problem:同样,我不知道您想如何处理空数据,所以我只是忽略了这个问题:
final _productMap = productSnap.data!.data()!;
ProductSize
constructorProductSize
构造函数时的值类型错误Inside product_page.dart
you have at line 114 the following:在
product_page.dart
您在第 114 行有以下内容:
ProductSize(
productSize: productSize,
onSelected: (size){
_selectedProductSize = size;
},
),
Your ProductSize
constructor is:您的
ProductSize
构造函数是:
final List? productSize;
final String? onSelected;
ProductSize({this.productSize, this.onSelected});
So you are trying to assign a method to onSelected
which takes a String?
所以你想给
onSelected
分配一个方法,它接受一个String?
as argument.作为论据。 I don't know what you are trying to do here but the current code does not make any sense.
我不知道你想在这里做什么,但当前的代码没有任何意义。
builder: (context, snapshot) {
if (snapshot.hasError) {
return Scaffold(
body: Center(
child: Text("Error: ${snapshot.error}"),
),
);
}
Convert the snapshot to AsyncSnapshot
snapshot to solve this error.将快照转换为
AsyncSnapshot
快照以解决此错误。 This works for me.这对我有用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.