. 你知道吗?Dart 支持字符串乘法。
这是一个简单的程序,显示如何使用字符串乘法打印圣诞树:
void main() { for (var i = 1; i <= 5; i++) { print('🎄' * i); } } // Output: // 🎄 // 🎄🎄 // 🎄🎄🎄 // 🎄🎄🎄🎄 // 🎄🎄🎄🎄🎄 复制代码
是不是很酷?😉
您可以使用它来检查长字符串如何适合Text
小部件:
Text('You have pushed the button this many times:' * 5) 复制代码
2.需要同时执行多个Future吗?使用 Future.wait。
考虑这个模拟 API 类,它告诉我们最新的 COVID 病例数:
// Mock API class class CovidAPI { Future<int> getCases() => Future.value(1000); Future<int> getRecovered() => Future.value(100); Future<int> getDeaths() => Future.value(10); } 复制代码
要同时执行所有这些futures,请使用Future.wait
. 这需要一个列表或 futures** and returns a future of lists:
final api = CovidAPI(); final values = await Future.wait([ api.getCases(), api.getRecovered(), api.getDeaths(), ]); print(values); // [1000, 100, 10] 复制代码
This is ideal when the futures are independent, and they don't need to execute sequentially.
3. 在 Dart 类中实现“调用”方法,使它们像函数一样可调用。
这是一个示例PasswordValidator
类:
class PasswordValidator { bool call(String password) { return password.length > 10; } } 复制代码
因为该方法名为call
,我们可以声明一个类实例并将其用作方法:
final validator = PasswordValidator(); // can use it like this: validator('test'); validator('test1234'); // no need to use it like this: validator.call('not-so-frozen-arctic'); 复制代码
4. 需要调用回调但前提是它不为空?使用“?.call()”语法。
假设我们有一个自定义小部件类,它应该onDragCompleted
在发生特定事件时调用回调:
class CustomDraggable extends StatelessWidget { const CustomDraggable({Key key, this.onDragCompleted}) : super(key: key); final VoidCallback? onDragCompleted; void _dragComplete() { // TODO: Implement me } @override Widget build(BuildContext context) {/*...*/} } 复制代码
要调用回调,我们可以编写以下代码:
void _dragComplete() { if (onDragCompleted != null) { onDragCompleted(); } } 复制代码
但是有一个更简单的方法(注意使用?.
):
Future<void> _dragComplete() async { onDragCompleted?.call(); } 复制代码
5. 使用匿名函数和函数作为参数
在 Dart 中,函数是一等公民,可以作为参数传递给其他函数。
下面是一些定义匿名函数并将其分配给sayHi
变量的代码:
void main() { final sayHi = (name) => 'Hi, $name'; welcome(sayHi, 'Andrea'); } void welcome(String Function(String) greet, String name) { print(greet(name)); print('Welcome to this course'); } 复制代码
然后sayHi
传递给一个welcome
函数,该函数接受一个Function
参数并使用它来迎接用户。
String Function(String)
是一个函数类型,它接受一个String
参数并返回一个String
. 因为上面的匿名函数具有相同的签名,它可以直接作为参数传递,也可以通过变量传递sayHi
。
使用功能等运营商时,这种编码风格是常见的map
,where
和reduce
。
例如,这是一个计算数字平方的简单函数:
int square(int value) { // just a simple example // could be a complex function with a lot of code return value * value; } 复制代码
给定一个值列表,我们可以映射它们以获得平方:
const values = [1, 2, 3]; values.map(square).toList(); 复制代码
这里我们square
作为参数传递,因为它的签名正是 map 操作符所期望的。这意味着我们不需要用匿名函数扩展它:
values.map((value) => square(value)).toList(); 复制代码
6. 您可以使用 collection-if 和 spreads 与lists, sets AND maps
当您将 UI 作为代码编写时,Collection-if 和 spreads 非常有用。
但是您知道您也可以将它们与maps一起使用吗?
考虑这个例子:
const addRatings = true; const restaurant = { 'name' : 'Pizza Mario', 'cuisine': 'Italian', if (addRatings) ...{ 'avgRating': 4.3, 'numRatings': 5, } }; 复制代码
这里我们声明一个restaurant
maps,只添加avgRating
和numRatings
键值对,如果addRatings
是true
。因为我们要添加多个键值对,所以我们需要使用扩展运算符 ( ...
)。
7. 需要以空安全的方式遍历map吗?使用.entries
:
假设你有map:
const timeSpent = <String, double>{ 'Blogging': 10.5, 'YouTube': 30.5, 'Courses': 75.2, }; 复制代码
以下是如何编写循环以使用所有键值对运行一些代码:
for (var entry in timeSpent.entries) { // do something with keys and values print('${entry.key}: ${entry.value}'); } 复制代码
通过迭代entries
变量,您可以以空安全的方式访问所有键值对。
这比这更简洁,更不容易出错:
for (var key in timeSpent.keys) { final value = timeSpent[key]!; print('$key: $value'); }