【问题标题】:The method 'forEach' can't be unconditionally invoked because the receiver can be 'null'方法 \'forEach\' 不能被无条件调用,因为接收者可以是 \'null\'
【发布时间】:2022-08-24 09:26:31
【问题描述】:

我想要做的是在我的 Firebase 数据库上获取密钥的值。

这是我的代码

import \'package:firebase_database/firebase_database.dart\';
import \'package:comment_app/post.dart\';

final dataReference = FirebaseDatabase.instance.ref().child(\'posts/\');
DatabaseReference savePost(Post post) {
  final id = dataReference.child(\'posts/\').push();
  id.set(post.toJson());
  return id;
}

void updatePost(Post post, DatabaseReference id) {
  id.update(post.toJson());
}

Future<List<Post>> getAllMessages() async {

  
  DataSnapshot? dataSnapshot =
      (await dataReference.child(\'posts/\').once()) as DataSnapshot;
    
  List<Post> posts = [];
 
  if (dataSnapshot.value != null) {
    dataSnapshot.value.forEach((key, value){ //Error highlights the forEach here.
      Post post = createPost(value);
      post.setId(dataReference.child(\'posts/\' + key));
      posts.add(post);
    });
  }
  return posts;
}

这是 post.dart 的代码

import \'package:comment_app/authentication/database.dart\';
import \'package:firebase_auth/firebase_auth.dart\';
import \'package:firebase_database/firebase_database.dart\';

class Post {
  String body;
  String author;
  Set userLikes = {};
  late DatabaseReference _id;
  Post(this.body, this.author);
  void likePost(User users) {
    if (userLikes.contains(users.uid)) {
      userLikes.remove(users.uid);
    } else {
      userLikes.add(users.uid);
    }
    this.update();
  }

  void update() {
    updatePost(this, _id);
  }

  void setId(DatabaseReference id) {
    _id = id;
  }

  Map<String, dynamic> toJson() {
    return {
      \'author\': author,
      \'userLikes\': userLikes.toList(),
      \'body\': body,
    };
  }
}



Post createPost(record) {
  
  Map<String, dynamic> attributes = {\'author\': \'\', \'userLikes\': [], \'body\': \'\'};
  record.forEach((key, value) => {attributes[key] = value});
  Post post = Post(attributes[\'body\'], attributes[\'author\']);
  post.userLikes = Set.from(attributes[\'userLikes\']);
  return post;
}

我刚刚开始学习使用 firebase 颤动,我收到了这个错误:

这是错误

方法 \'forEach\' 不能被无条件调用,因为 接收者可以是\'null\'。尝试使调用有条件(使用 \'?.\') 或向目标添加空检查 (\'!\')。

I\'m trying to get the author and body of each key in my firebase database

  • 请粘贴并格式化您的代码。不是照片,尤其不是照片的链接。
  • 请不要发布您的代码的屏幕截图或其他文本内容。而是发布实际文本,并使用 Stack Overflow 的格式化工具对其进行标记。另见:Why not upload images of code/errors when asking a question?
  • 嗨,我已经编辑了我的问题,无论如何感谢我对堆栈溢出不熟悉的信息。

标签: flutter firebase-realtime-database


【解决方案1】:

所以错误告诉你你想运行something.forEach。但是flutter不知道something是否为null,如果为null,它不能运行foreach,所以它要求你告诉它如果它为null它应该做什么。我们首先需要弄清楚something 是什么。您在代码中调用 .forEach 两次:

dataSnapshot.value.forEach

record.forEach

我不知道哪个可能导致错误,但是如果您查看错误消息,它应该会告诉您正在发生的确切行和文件,因此请尝试自己弄清楚。

在第一次通话中,您已经通过添加以下行确保 dataSnapshot.value 不为空:

if (dataSnapshot.value != null) {

通常,dart 足够聪明,可以找出 dataSnapshot.value 不为空,但我想在这种情况下,它有可能不知道一个值可能为空,不是,您可以在空值之后使用! 表达式。

dataSnapshot.value!.forEach

请记住,如果 dataSnapshot.value 为 null,您的应用程序会崩溃,因此请仅在您使用 !知道值不为空。另外,正如我所说,dart 可能足够聪明,知道dataSnapshot.value 不为空,所以你可能不需要这样做,真正的罪魁祸首可能是record

第二次使用它是在record.forEach,所以让我们看一下记录的类型,以确定它可以为空或不为空:

Post createPost(record) {
  ...
}

这是什么?你没有给record任何类型!难怪 dart 不相信它不会为空。无论record 应该是什么,请确保添加一个类型,如果它可以为空,那么您应该在运行之前添加一个空检查,就像您在dataSnapshot 上所做的那样

【讨论】:

  • forEach 错误突出了这部分>>dataSnapshot.value.forEach((key, value),所以我觉得post.dart 中的forEach 就可以了,我也试过这个"dataSnapshot.value!.forEach" 错误改成这:没有为“Object”类型定义方法“forEach”。尝试将名称更正为现有方法的名称,或定义一个名为“forEach”的方法。(仍然是来自 dataSnapshot.value.forEach 的 forEach 错误)
  • 很难解决此问题,因为您正在使用大量动态值。而且我不知道这些值是什么应该成为。你可以试试这样做吗? (dataSnaoshot!.value! as List).forEach( 看看它是否有效?
【解决方案2】:

你有两个问题:

1.Dart 不承认你已经检查过 dataSnapshot.value 为空:

if (dataSnapshot.value != null) {
    dataSnapshot.value.forEach((key, value){
要解决此问题,您只需添加“!”在value前面:
    dataSnapshot.value!.forEach((key, value){

2.forEach 方法未定义:

没有为“对象”类型定义方法“forEach”。 尝试将名称更正为现有方法的名称,或定义名为“forEach”的方法。dartundefined_method

这是因为forEach 通常不能在Future&lt;T&gt; 函数中工作。

要让forEach 按预期工作,您需要首先从Future 调用它,在这种情况下这不起作用,因为您必须将dataSnapshot.value 传递给forEach() 方法,这样做会破坏代码.

Future.forEach(elements, (element));  // This is an example of what it would look like

处理此问题的典型方法是重构代码以适应 for 循环或尝试不同的方法。 我发现将forEach() 方法与Future&lt;T&gt; 函数分离为Future 函数以使其正常运行也同样有效。

我最近在尝试更新版本的 firebase 时遇到了同样的问题,这就是我修复它的方法:
// New function using the regular Future, forEach() works normally
Future snapshotValue(dataSnapshot, posts) async {
  dataSnapshot.value!.forEach((key, value) {
    Post post = createPost(value);
    post.setId(databaseReference.child("posts/" + key));
    posts.add(post);
  });
}

// Future<t> function, only supports Future.forEach()
Future<List<Post>> getAllMessages() async {
  DataSnapshot dataSnapshot = (await databaseReference.child("posts/").once()).snapshot;
  List<Post> posts = [];
  if (dataSnapshot.value != null) {
    snapshotValue(dataSnapshot, posts);
  }
  return posts;
}

上面的代码在firebase_database: ^9.1.2firebase_auth: ^3.6.4 上进行了测试。

【讨论】:

    猜你喜欢
    • 2023-04-10
    • 2022-08-21
    • 2022-08-15
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    • 2021-10-05
    • 1970-01-01
    • 2021-08-27
    相关资源
    最近更新 更多