Skip to content
Calvin's Blog

Dart SDK 中鲜为人知的类和函数

Nov 29, 2024 — Flutter

最近,Flutter 社区 itsallwidgets (opens in a new window) 建了一个论坛 (opens in a new window),目前加入的人不多,大家可以注册账号,跟国外的活跃开发者们一起讨论关于 Flutter 开发的话题。

虽然人不多,但也有一些比较有意思的主题讨论,其中一个主题是: Lesser known classes and functions from the Dart core libraries (opens in a new window) ,讨论一些日常开发中比较少用到,但是却很有意思和实用的类和函数。

本文分成两部分,第一部分是对论坛评论里提到的类和函数进行总结,第二部分将额外补充一些没有提到的。

第一部分:论坛评论

1. package:collection中的minBy()maxBy()函数

import 'package:collection/collection.dart';
void main() {
final numbers = [5, 3, 8, 1, 9];
final minNumber = numbers.minBy((num) => num);
final maxNumber = numbers.maxBy((num) => num);
print('最小值: $minNumber');
print('最大值: $maxNumber');
}

2. Iterable<T>nonNulls扩展

void main() {
final listWithNulls = [1, null, 3, null, 5];
final nonNullList = listWithNulls.nonNulls;
print(nonNullList);
}

3. package:asyncAsyncCache.ephemeral

import 'package:async/async.dart';
Future<void> asyncOperation() async {
await Future<void>.delayed(const Duration(seconds: 2));
print('Executed');
}
void main() {
final AsyncCache _cache = AsyncCache.ephemeral();
ElevatedButton(
onPressed: () => _cache.fetch(asyncOperation),
child: const Text('Execute'),
);
}

在上述代码中,多次点击按钮时,asyncOperation函数只会执行一次,直到其完成。

4. firstWhereOrNull

class MyStuff {
final String id;
MyStuff(this.id);
}
void main() {
final someStuffs = [MyStuff('Dog'), MyStuff('Cat'), MyStuff('Bird')];
MyStuff? stuff = someStuffs.firstWhereOrNull((element) => element.id == 'Cat');
print(stuff);
}

5. 解码 HTTP 响应的优化方式

import 'dart:convert';
import 'dart:isolate';
import 'package:http/http.dart' as http;
Future<Map<String, dynamic>?> isolateHttpResponseDecoder(
http.Response httpResponse,
) async =>
Isolate.run(
() => const Utf8Decoder().fuse(const JsonDecoder()).convert(httpResponse.bodyBytes) as Map<String, dynamic>?,
);
void main() async {
final response = await http.get(Uri.parse('https://example.com/api/data'));
final decodedData = await isolateHttpResponseDecoder(response);
print(decodedData);
}

6. FutureRecord2扩展

Future<String> fetchText() async {
await Future.delayed(Duration(seconds: 1));
return 'Hello';
}
Future<String> fetchImage() async {
await Future.delayed(Duration(seconds: 2));
return 'Image data';
}
void main() async {
var (text, image) = await (fetchText(), fetchImage()).wait;
print('Text: $text');
print('Image: $image');
}

7. Completer<T>

import 'dart:async';
void main() {
final completer = Completer<String>();
// 模拟一个异步操作,在2秒后完成Future并传递数据
Future.delayed(Duration(seconds: 2), () {
completer.complete('Data from async operation');
});
// 等待Future完成并获取结果
completer.future.then((value) {
print(value);
});
}

8. unawaited函数

import 'dart:async';
void main() {
// 模拟一个异步后台任务
Future<void> performBackgroundTask() async {
await Future.delayed(Duration(seconds: 1));
print('后台任务完成');
}
// 使用 unawaited 表明无需等待任务完成
unawaited(performBackgroundTask());
// 继续执行其他逻辑
print('主线程继续执行');
}

第二部分:额外补充

搜集一些网络上和自己日常开发中遇到的类和函数。

List.generate 函数

void main() {
List<int> numbers = List.generate(10, (index) => index);
print(numbers);
}
void main() {
List<String> greetings = List.generate(5, (index) => "Hello");
print(greetings);
}

StringBuffer类和相关函数

void main() {
StringBuffer buffer = StringBuffer();
buffer.write("Hello");
buffer.write(" ");
buffer.write("World");
String sentence = buffer.toString();
print(sentence);
}

Iterable.whereType 函数

void main() {
List<Object> objects = [1, "two", 3.0, true, "four"];
// 筛选出字符串类型的元素
Iterable<String> strings = objects.whereType<String>();
print(strings.toList());
}

Iterable.reduce函数

void main() {
List<int> numbers = [1, 2, 3, 4, 5];
int sum = numbers.reduce((value, element) => value + element);
print(sum);
}
void main() {
List<int> numbers = [2, 3, 4];
int product = numbers.reduce((value, element) => value * element);
print(product);
}

Map.fromIterable函数

void main() {
List<int> numbers = [1, 2, 3, 4, 5];
Map<int, int> numberMap = Map.fromIterable(
numbers,
key: (number) => number,
value: (number) => number * number,
);
print(numberMap);
}

Map.putIfAbsent 函数

void main() {
Map<String, int> map = {};
// 如果键 "key1" 不存在,则添加键值对 "key1": 10
int value1 = map.putIfAbsent("key1", () => 10);
print(value1);
// 键 "key1" 已存在,返回其对应的值 10
int value2 = map.putIfAbsent("key1", () => 20);
print(value2);
}

Uri.encodeComponent 函数

void main() {
String url = "https://www.example.com/search?q=Dart 编程";
// 使用 Uri.encodeFull 对整个 URL 进行编码
String encodedUrlFull = Uri.encodeFull(url);
print(encodedUrlFull);
// 使用 Uri.encodeComponent 对查询参数进行编码
String query = "Dart 编程";
String encodedQuery = Uri.encodeComponent(query);
print(encodedQuery);
}

UriData

void main() {
final uriData = UriData.fromString('Hello, Dart!', mimeType: 'text/plain');
print(uriData.toString()); // 输出: data:text/plain;base64,SGVsbG8sIERhcnQh
}

String.padLeftString.padRight 函数

void main() {
String number = "123";
// 在左侧填充 0,使字符串长度为 5
String paddedNumberLeft = number.padLeft(5, '0');
print(paddedNumberLeft);
// 在右侧填充空格,使字符串长度为 6
String paddedNumberRight = number.padRight(6);
print(paddedNumberRight);
}

Expando

void main() {
final expando = Expando<String>('labels');
final obj1 = Object();
final obj2 = Object();
expando[obj1] = 'First Object';
expando[obj2] = 'Second Object';
print(expando[obj1]); // 输出: First Object
print(expando[obj2]); // 输出: Second Object
}

WeakReference

import 'dart:core';
void main() {
final obj = Object();
final weakRef = WeakReference(obj);
print(weakRef.target); // 输出: Instance of 'Object'
// 如果 obj 被释放,weakRef.target 会变为 null
}

Stopwatch

void main() {
final stopwatch = Stopwatch()..start();
// 模拟耗时操作
for (int i = 0; i < 1000000; i++) {}
stopwatch.stop();
print('Elapsed time: ${stopwatch.elapsedMilliseconds}ms');
}

RuneIterator

void main() {
final input = '👋🌍';
final iterator = RuneIterator(input);
while (iterator.moveNext()) {
print(iterator.currentAsString); // 输出: 👋 然后 🌍
}
}