Flutter:避免将“forEach”与函数文字一起使用

del*_*ram 39 dart flutter

大家好,这是我的整个方法:

Future<void> init() async {
    FirebaseAuth.instance.userChanges().listen((user) {
      if (user != null) {
        _loginState = ApplicationLoginState.loggedIn;
        _guestBookSubscription = FirebaseFirestore.instance
            .collection('guestbook')
            .orderBy('timestamp', descending: true)
            .limit(3)
            .snapshots()
            .listen((snapshot) {
          _guestBookMessages = [];
          snapshot.docs.forEach((document) {
            _guestBookMessages.add(
              GuestBookMessage(
                name: document.data()['name'] as String,
                message: document.data()['text'] as String,
              ),
            );
          });
          notifyListeners();
        });
      } else {
        _loginState = ApplicationLoginState.loggedOut;
        _guestBookMessages = [];
        _guestBookSubscription?.cancel();
      }
      notifyListeners();
    });
  }
Run Code Online (Sandbox Code Playgroud)

dart 抱怨的部分是:

snapshot.docs.forEach((document) {
            _guestBookMessages.add(
              GuestBookMessage(
                name: document.data()['name'] as String,
                message: document.data()['text'] as String,
              ),
            );
          });
Run Code Online (Sandbox Code Playgroud)

我怎样才能改变这个方法而不破坏整个功能?我只是在寻找一种让 dart 快乐的方法。我提前感谢您的帮助。

Sif*_*min 52

避免将 forEach 与函数文字一起使用。

避免:

snapshot.docs.forEach((document) {
  ...
});
Run Code Online (Sandbox Code Playgroud)

好的:

for (var document in snapshot.docs) {
  // Rest of your code
}
Run Code Online (Sandbox Code Playgroud)

  • 说实话这太荒谬了。他们应该改进他们的编译器/解释器,而不是给出这样的建议。 (10认同)
  • @BugsHappen 可能是因为它会让代码看起来更复杂。建议要么像上面建议的 Sifat 那样做,或者我认为更好的是创建另一个提供给 `forEach` 方法的函数。此处描述:[链接](https://dart.dev/guides/language/ effective-dart/usage#avoid-using-iterableforeach-with-a-function-literal)引用:“如果你想调用一些每个元素上已经存在函数,forEach() 就可以了。” 因此定义一个新函数并在“forEach”中使用它。 (9认同)
  • 您能解释一下为什么其中一个是好/坏吗? (7认同)
  • 同意,“好/坏”术语没有帮助。我认为在大多数语言中,使用循环比重复调用匿名函数性能更高。这是因为函数会带来分配和清理堆栈的开销,而循环会被编译器优化为更“扁平”的代码。我认为这里也是这种情况,也是 Dart 发出警告的原因。 (6认同)
  • 我认为后者可读性较差 (5认同)

小智 5

使用类似的data.forEach(function); 例子:

void main() async {
  List<int> list = [1, 2, 3, 4, 5];

  //recommended
  list.forEach(showSquareNumbers);

  //not recommended
  list.forEach((int number) => showSquareNumbers(number));
  list.forEach((int number) {
    showSquareNumbers(number);
  });
}

void showSquareNumbers(int data) {
  print("$data * $data = ${data * data}");
}
Run Code Online (Sandbox Code Playgroud)

这是我的意见。

我认为这forEach似乎比for循环更复杂,并且forEach不能使用continueand breakreturn可用,但使用时不会发生任何事情return)。

void test(List data) {
  data.forEach((element) {
    print(element);
    if(element) return;
  });

  for (var element in data) {
    print(element);
    if(element) continue;
    if(element) break;
    if(element) return;
  }
}
Run Code Online (Sandbox Code Playgroud)

我认为当您的循环看起来像下面的代码时,我们应该使用 thefor而不是循环,因为循环比我所说的有更多选项。forEachforEachforforEach

  data.forEach((element) {
    print(element)
  });
  //or
  data.forEach((element) => print(element));
Run Code Online (Sandbox Code Playgroud)

我认为forEach循环用于短代码(易于理解),当您想做一些事情时,您不关心像此代码这样的结果(使用 with Function(dynamic))。

void test(List data) {
  void showInTerminal(e) {
    print("data is $e");
  }
  data.forEach(showInTerminal);
  
  Function(dynamic) function = showInTerminal;
  data.forEach(function);
}
Run Code Online (Sandbox Code Playgroud)

确保数据类型和函数(类型)相同。

//error
void test(List<Map> data) {
  void showInTerminal(String e) {
    print("data is $e");
  }
  data.forEach(showInTerminal);
}

//success
void test(List<Map> data) {
  void showInTerminal(Map e) {
    print("data is $e");
  }
  data.forEach(showInTerminal);
}
Run Code Online (Sandbox Code Playgroud)

我这样编码。我认为这很容易阅读。

void test() {
  dataList.forEach(removeData);
  fileList.forEach(removeFile);
}
Run Code Online (Sandbox Code Playgroud)