Files
blog-press/docs/Flutter/DartGuide.md
2025-12-05 17:36:33 +08:00

372 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 一、基础语法
## 1.1 变量与常量
```dart
// 显式声明类型
String name = 'Dart';
int age = 10;
// 类型推断(使用 var
var city = 'Beijing'; // 自动推断为 String
var count = 100; // 自动推断为 int
// 延迟初始化
String? email; // 可空类型
late String description; // 延迟初始化
const PI = 3.14159;
const List<int> nums = [1, 2, 3]; // 不可修改的列表
final currentTime = DateTime.now(); // 运行时才知道值
final List<int> numbers = [1, 2, 3];
numbers.add(4); // 可以!列表内容可修改
dynamic value = 'Hello';
value = 123; // 可以
value = true; // 可以
// 非空类型(默认)
String name = 'Dart';
// name = null; // 错误!
// 可空类型(使用 ?
String? nickname;
nickname = null; // 正确
// 空值断言(!
String? value = 'Hello';
print(value!.length); // 确信不为null时使用
// 空值合并运算符(??
String? name;
String displayName = name ?? 'Guest'; // name为null时使用'Guest'
// 条件访问(?.
String? text;
print(text?.length); // text为null时返回null不报错
```
&emsp;&emsp;const常量值在编译期就确定对象及其内容都不可变。
&emsp;&emsp;final常量值在运行时确定但只能赋值一次引用不可变但对象内容可能可变。
## 1.2 数据类型
```dart
// 单引号或双引号
String str1 = 'Hello';
String str2 = "World";
// 字符串插值
String name = 'Dart';
int version = 3;
print('$name $version');
print('${name version}');
// int - 整数
int count = 10;
int hex = 0xDEADBEEF;
// double - 浮点数
double price = 19.99;
double exponent = 1.42e5; // 科学计数法
// num - int 和 double 的父类
num value1 = 10;
num value2 = 10.5;
// 常用方法
int a = 5;
double b = 3.14159;
print(b.toStringAsFixed(2)); // 3.14
print(int.parse('42')); // 字符串转int
print(double.parse('3.14')); // 字符串转double
bool isActive = true;
bool isCompleted = false;
// 创建列表
List<int> numbers = [1, 2, 3, 4, 5];
var fruits = ['apple', 'banana', 'orange'];
// 访问元素
print(numbers[0]); // 1
print(numbers.length); // 5
// 添加元素
numbers.add(6);
numbers.addAll([7, 8, 9]);
// 删除元素
numbers.remove(3); // 删除值为3的元素
numbers.removeAt(0); // 删除索引0的元素
// 常用方法
print(numbers.first); // 第一个元素
print(numbers.last); // 最后一个元素
print(numbers.isEmpty); // 是否为空
numbers.forEach((num) => print(num)); // 遍历
// 不可变列表
const fixedList = [1, 2, 3];
// 扩展运算符
var list1 = [1, 2, 3];
var list2 = [0, ...list1]; // [0, 1, 2, 3]
// 创建 Map
Map<String, int> ages = {
'Alice': 25,
'Bob': 30,
'Charlie': 35
};
// 访问元素
print(ages['Alice']); // 25
// 添加/修改元素
ages['David'] = 28;
ages['Alice'] = 26;
// 删除元素
ages.remove('Bob');
// 常用方法
print(ages.keys); // 所有键
print(ages.values); // 所有值
print(ages.length); // 元素个数
print(ages.isEmpty); // 是否为空
print(ages.containsKey('Alice')); // 是否包含键
// 遍历
ages.forEach((key, value) {
print('$key: $value');
});
```
# 二、函数
```dart
// 简写(箭头函数,适用于单行表达式)
String greet2(String name) => 'Hello, $name!';
// 必传参数
int add(int a, int b) {
return a + b;
}
// 可选位置参数(用 [] 包裹,可提供默认值)
String introduce(String name, [int? age, String city = 'Beijing']) {
if (age != null) {
return '$name, $age years old, from $city';
}
return '$name from $city';
}
// 调用示例
print(introduce('Alice')); // Alice from Beijing
print(introduce('Bob', 25)); // Bob, 25 years old, from Beijing
print(introduce('Charlie', 30, 'Shanghai')); // Charlie, 30 years old, from Shanghai
// 命名参数(用 {} 包裹)
void createUser({
required String name, // required 表示必传
int age = 18, // 有默认值
String? email // 可选可为null
}) {
print('Name: $name, Age: $age, Email: $email');
}
// 调用时使用参数名
createUser(name: 'Alice');
createUser(name: 'Bob', age: 25, email: 'bob@example.com');
// 命名参数的优点:顺序无关,更清晰
void setStyle({String? color, double? size, bool? bold}) {
// ...
}
setStyle(bold: true, color: 'red'); // 顺序可以任意
```
# 三、类
```dart
class BankAccount {
String accountNumber; // 公有属性
double _balance; // 私有属性以_开头
BankAccount(this.accountNumber, this._balance);
// 公有方法
double getBalance() {
return _balance;
}
// 私有方法
void _updateBalance(double amount) {
_balance += amount;
}
void deposit(double amount) {
if (amount > 0) {
_updateBalance(amount);
}
}
// Getter
double get balance => _balance;
// Setter
set balance(double value) {
if (value >= 0) {
_balance = value;
}
}
}
// 使用
var account = BankAccount('123456', 1000);
print(account.balance); // 使用getter1000
account.deposit(500);
print(account.balance); // 1500
account.balance = 2000; // 使用setter
```
# 四、任务
```dart
void eventLoopExample() {
print("主线程开始");
// 微任务
scheduleMicrotask(() {
print("微任务1");
});
// 异步任务
Future.delayed(Duration(seconds: 0), () {
print("异步任务1");
});
// 再次添加微任务
scheduleMicrotask(() {
print("微任务2");
});
print("主线程结束");
}
//输出结果:
主线程开始
主线程结束
微任务1
微任务2
异步任务1
```
&emsp;&emsp;在 Dart 的事件循环中,执行顺序如下:
1. 同步代码:首先执行所有同步代码。
2. 微任务队列:然后依次执行微任务队列中的所有微任务。
3. 事件队列:最后执行事件队列中的异步任务。
# 五、异步编程
```dart
// 1. Future() 构造函数
Future<int> calculateSum(int a, int b) {
return Future(() {
return a + b;
});
}
// 2. Future.value() - 立即完成
Future<String> immediateFuture = Future.value("立即结果");
// 3. Future.error() - 立即失败
Future<void> errorFuture = Future.error("错误信息");
// 4. Future.delayed() - 延迟执行
Future<String> delayedFuture = Future.delayed(
Duration(seconds: 3),
() => "延迟结果"
);
// 5. Future.sync() - 同步执行
Future<int> syncFuture = Future.sync(() => 42);
// 从网络请求
Future<http.Response> fetchUserData() async {
return await http.get(Uri.parse('https://api.example.com/user'));
}
// 文件操作
Future<File> writeToFile(String content) async {
final file = File('data.txt');
return await file.writeAsString(content);
}
```
&emsp;&emsp;其他用法:
```dart
Future<void> processData() async {
try {
print("开始获取数据...");
// 等待第一个 Future
final data1 = await fetchDataFromSource1();
print("数据1: $data1");
// 等待第二个 Future
final data2 = await fetchDataFromSource2();
print("数据2: $data2");
// 处理结果
final result = await processCombinedData(data1, data2);
print("最终结果: $result");
} catch (e) {
print("处理过程中出错: $e");
} finally {
print("清理资源");
}
}
// 1. Future.wait() - 等待所有完成
Future<void> fetchAllData() async {
final futures = [
fetchUserData(),
fetchProductData(),
fetchOrderData(),
];
try {
final results = await Future.wait(futures);
print("所有数据获取完成: $results");
} catch (e) {
print("部分请求失败: $e");
}
}
// 2. Future.any() - 第一个完成
Future<String> getFastestResponse() {
return Future.any([
fetchFromServer1(),
fetchFromServer2(),
fetchFromServer3(),
]);
}
// 3. Future.forEach() - 顺序执行
Future<void> processItems(List<String> items) async {
await Future.forEach(items, (item) async {
await processItem(item);
});
}
// 4. 链式操作
Future<String> complexOperation() {
return authenticateUser()
.then((token) => fetchUserProfile(token))
.then((profile) => updateProfile(profile))
.then((updated) => saveToDatabase(updated))
.then((savedId) => "操作完成ID: $savedId")
.catchError((error) {
// 统一错误处理
print("链式操作失败: $error");
return "默认值";
});
}
```