繁体   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,
          ),
        ],
      ),
    );
  }
}

您的代码中存在多个问题(取自您的 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<dynamic> 如果您在两种情况下阅读.collection的返回类型,您将看到返回的类型是CollectionReference<Map<String, dynamic>>

这很重要,因为在程序中的其他位置调用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<Object?>类型, AsyncSnapshot<Object?>不是那么具体。 如果您查看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<String, dynamic>?' 类型的值不能分配给类型为“Map<dynamic, dynamic>”的变量。

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

final _productMap = productSnap.data.data();

缺少对可能的null值的处理

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

方法 'data' 不能无条件调用,因为接收者可以为 '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? 作为论据。 我不知道你想在这里做什么,但当前的代码没有任何意义。

builder: (context, snapshot) {
              if (snapshot.hasError) {
                return Scaffold(
                  body: Center(
                    child: Text("Error: ${snapshot.error}"),
                  ),
                );
              }

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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