【问题标题】:Error: The method 'data' isn't defined for the class 'Object?'错误:没有为类“对象”定义方法“数据”?
【发布时间】:2021-07-18 18:45:56
【问题描述】:
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,
          ),
        ],
      ),
    );
  }
}

【问题讨论】:

  • _firebaseServices.productRef 是什么类型?您能否说明FirebaseServices 类中如何定义该字段?
  • 这里的兄弟你可以从这里下载源代码:github.com/Bhaskar2510/Final-Sem还有一些错误,如果你能帮忙

标签: android flutter dart flutter-layout flutter-dependencies


【解决方案1】:

您的代码中存在多个问题(取自您的 GitHub 存储库。)。我将尝试在这里列出所有问题,并对每个问题进行一些解释。一个常见的主题是对使用泛型的误解,因此我建议您阅读它们:

https://dart.dev/guides/language/language-tour#generics

我强烈建议您在代码中尽可能具体地使用您的所有类型,因为当前的许多行为都在使用dynamic,而这并不是真正需要的。通过使代码更加静态类型安全,您还可以让编译器发现很多错误,否则会导致运行时崩溃。

以下发现的问题不是完整列表,因为您的大多数问题与其中一个问题具有相同的潜在问题。

泛型类型已被移除

firebase_services.dart 你有这个:

  final CollectionReference productRef =
      FirebaseFirestore.instance.collection("Products");

  final CollectionReference usersRef =
      FirebaseFirestore.instance.collection("Users");

这是不正确的,因为您要从 CollectionReference 中删除泛型类型,所以它变成了 CollectionReference&lt;dynamic&gt;。如果你在这两种情况下都阅读了.collection的返回类型,你会看到返回的类型是CollectionReference&lt;Map&lt;String, dynamic&gt;&gt;

这很重要,因为在程序中的其他位置调用 CollectionReference 对象上的方法时会使用此类型。

所以应该改成:

  final CollectionReference<Map<String, dynamic>> productRef =
      FirebaseFirestore.instance.collection("Products");

  final CollectionReference<Map<String, dynamic>> usersRef =
      FirebaseFirestore.instance.collection("Users");

缺少使用FutureBuilder的泛型

cart_page.dart 中,您有以下第 52 行:

                      child: FutureBuilder(
                        future:
                            _firebaseServices.productRef.doc(document.id).get(),
                        builder: (context, productSnap) {

如果你检查 productSnap 的解析类型,你可以看到 Dart 认为它的类型 AsyncSnapshot&lt;Object?&gt; 不是那么具体。如果您查看FutureBuilder 的文档,它表明您应该将它与一个泛型类型一起使用,该类型告诉您希望Future 返回什么类型:

https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html

所以把FutureBuilder的定义改成:

child: FutureBuilder<DocumentSnapshot<Map<String, dynamic>>>(

另一个示例在第 20 行的同一文件中:

          FutureBuilder<QuerySnapshot>(
            future: _firebaseServices.usersRef
                .doc(_firebaseServices.getUserId())
                .collection("Cart")
                .get(),
            builder: (context, snapshot) {

在这里,您有 QuerySnapshot,但忘记了它也接受泛型参数。所以根据future 段的返回值,这应该是:

FutureBuilder<QuerySnapshot<Map<String, dynamic>>>(

变量声明中缺少泛型

随着我们在代码中更具体的类型,我们遇到了这个错误(仍在cart_page.dart),这给了我们一个错误:

                          if (productSnap.connectionState ==
                              ConnectionState.done) {
                            Map _productMap = productSnap.data.data();

'Map?' 类型的值不能分配给“地图”类型的变量。

这里的问题是,通过写Map,你实际上是在写Map&lt;dynamic, dynamic&gt;,这将删除重要的类型信息。我建议只使用 varfinal 并让 Dart 自动为变量分配最佳类型:

final _productMap = productSnap.data.data();

缺少可能的null值处理

让我们继续使用完全相同的行。现在我们得到以下错误:

方法'data'不能被无条件调用,因为receiver可以是'null'。

问题是data 属性可以是null,以防发生错误。我不知道你现在想如何处理这个问题,我将忽略这个问题并使用! 强制添加运行时空检查:

final _productMap = productSnap.data!.data();

但这还不够,因为data() 的输出也可以是您的代码未处理的null。同样,我不知道你想如何处理空数据,所以我只是忽略了这个问题:

final _productMap = productSnap.data!.data()!;

调用ProductSize构造函数时的值类型错误

product_page.dart 的第 114 行有以下内容:

                  ProductSize(
                    productSize: productSize,
                    onSelected: (size){
                      _selectedProductSize = size;
                    },
                  ),

您的ProductSize 构造函数是:

  final List? productSize;
  final String? onSelected;
  ProductSize({this.productSize, this.onSelected});

因此,您正在尝试为 onSelected 分配一个方法,该方法将 String? 作为参数。我不知道你想在这里做什么,但当前的代码没有任何意义。

【讨论】:

  • 对所有这些都是新手很好。但我建议您从学习 Dart 开始(从语言之旅开始:dart.dev/guides/language/language-tour),然后在编写代码时从头开始慢慢构建您的应用程序并纠正所有错误和警告。正如您现在的代码一样,确实有太多不同的可重复类型的错误,无法在不写一本书的情况下进行简单的解释。所以学习 Dart 并学习编写类型安全的代码。什么能解决你90%的问题。然后还阅读有关 null 安全性的信息:dart.dev/null-safety
  • 嘿!感谢您的帮助实际上我是一个初学者,所以我对您刚刚告诉我的事情不太了解。感谢您为解决我的错误所付出的所有时间和精力。通过所选代码上的产品尺寸页面上的最后一个,我试图从产品尺寸页面获取尺寸值。这在该视频的 14:00 分钟中被告知。所以,如果你能让我知道正确的方式,我会很幸运。 youtube.com/watch?v=ts9D2312FkY 在我的自定义操作栏页面中。我还需要添加 > 吗?
  • 是的!一旦我完成了这个项目,我肯定会阅读这些内容,因为我必须在明天之前将它提交给我的大学。这就是为什么我一次又一次地打扰你,我真的很抱歉。
  • @Bhaskar2510 您可以看到您的ProductSize 课程与视频中的课程不同:github.com/akshayejh/a_commerce/blob/master/lib/widgets/…onSelected 不应该是 String 而是 Function(String),这意味着一个以 String 作为参数的函数。
  • 哦!我现在明白了。谢谢。我应该为我的自定义操作栏页面做些什么,这是最后一个错误?
【解决方案2】:
builder: (context, snapshot) {
              if (snapshot.hasError) {
                return Scaffold(
                  body: Center(
                    child: Text("Error: ${snapshot.error}"),
                  ),
                );
              }

将快照转换为AsyncSnapshot 快照以解决此错误。这对我有用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-16
    • 2021-02-24
    • 2021-07-26
    • 2021-04-15
    • 2020-05-21
    • 2019-05-10
    • 1970-01-01
    相关资源
    最近更新 更多