简体   繁体   English

错误:未为类“Object?”定义方法“data”

[英]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.以下发现的问题不是完整列表,因为您的大多数问题与其中一个具有相同的潜在问题。

Generic types has been removed通用类型已被删除

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");

Missing generic with use of 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>>>(

Missing generic in variable declaration变量声明中缺少泛型

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:我建议只使用varfinal并让 Dart 自动为变量分配最佳类型:

final _productMap = productSnap.data.data();

Missing handling of possible null value缺少对可能的null值的处理

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()!;

Wrong value type when calling ProductSize constructor调用ProductSize构造函数时的值类型错误

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM