Dart语言快速入门:Flutter开发的基石
掌握现代跨平台开发的核心语言,开启高效移动应用开发之旅
引言:为什么选择Dart?
Dart是Google开发的面向对象的编程语言,专门为构建Web、服务器和移动应用而设计。作为Flutter框架的官方语言,Dart结合了JavaScript的灵活性和Java的稳健性,提供了出色的开发体验。
关键优势:
- 🚀 高性能:AOT和JIT编译支持
- 📱 跨平台:一套代码多端运行
- 🎯 易学习:语法类似Java/JavaScript
- 🔥 热重载:极速开发调试体验
1. 变量与数据类型
1.1 变量声明
Dart提供了多种变量声明方式,每种都有不同的语义和用途:
void main() {
// 1. var - 类型推断
var name = 'Dart'; // 推断为String类型
var version = 2.12; // 推断为double类型
// 2. dynamic - 动态类型
dynamic dynamicValue = 'Hello';
dynamicValue = 100; // 可以重新赋值为不同类型
dynamicValue = true; // 再次改变类型
// 3. final - 运行时常量
final currentTime = DateTime.now(); // 运行时确定值
// 4. const - 编译时常量
const pi = 3.14159;
const maxSize = 100;
// 5. 显式类型声明
String language = 'Dart';
int year = 2024;
double score = 95.5;
bool isCompleted = true;
print('变量声明示例完成');
}
1.2 基本数据类型
Dart的所有类型都是对象,没有原始类型(primitive types)的概念。
数值类型
void numberTypes() {
// 整数类型
int age = 25;
int hex = 0xDEADBEEF;
int population = 8000000000;
// 浮点数类型
double height = 1.75;
double price = 9.99;
double scientific = 1.5e6; // 1.5 × 10^6
// num类型 - int和double的父类
num flexibleNumber = 10; // 可以是整数
flexibleNumber = 10.5; // 也可以是浮点数
// 数值操作
print('年龄: $age');
print('身高: $height 米');
print('十六进制: $hex');
print('科学计数法: $scientific');
// 类型转换
String text = '123';
int number = int.parse(text);
double decimal = double.parse('3.14');
String numberText = 123.toString();
String piText = 3.14159.toStringAsFixed(2); // "3.14"
}
字符串类型
void stringTypes() {
// 字符串声明方式
String single = '单引号字符串';
String double = "双引号字符串";
String multiLine = '''
多行
字符串
示例
''';
// 字符串插值
String name = '小明';
int score = 95;
String message = '$name的考试成绩是$score分';
String calculation = '1 + 2 = ${1 + 2}';
// 字符串操作
String greeting = 'Hello, World!';
print(greeting.length); // 13
print(greeting.toUpperCase()); // HELLO, WORLD!
print(greeting.contains('World')); // true
print(greeting.substring(7)); // World!
// 原始字符串
String raw = r'原始字符串 \n 不会转义';
print(raw); // 输出: 原始字符串 \n 不会转义
}
布尔类型
void booleanTypes() {
bool isActive = true;
bool isCompleted = false;
// Dart只有true是true,其他所有值都是false
var emptyString = '';
var zero = 0;
var nullValue = null;
print(emptyString is bool); // false
print(zero is bool); // false
// 条件判断
if (isActive && !isCompleted) {
print('任务进行中');
}
}
1.3 集合类型
List(列表)
void listExamples() {
// List声明方式
List<int> numbers = [1, 2, 3, 4, 5];
var names = ['Alice', 'Bob', 'Charlie']; // 类型推断
List<dynamic> mixed = [1, 'hello', true, 3.14];
// 固定长度List
List<int> fixedList = List.filled(3, 0); // [0, 0, 0]
// List操作
numbers.add(6); // 添加元素
numbers.insert(0, 0); // 插入元素
numbers.remove(3); // 删除元素
numbers.removeAt(1); // 删除指定位置元素
print('列表长度: ${numbers.length}');
print('第一个元素: ${numbers.first}');
print('最后一个元素: ${numbers.last}');
print('是否为空: ${numbers.isEmpty}');
// List遍历
for (int i = 0; i < numbers.length; i++) {
print('索引$i: ${numbers[i]}');
}
// for-in循环
for (var number in numbers) {
print('数字: $number');
}
// forEach方法
numbers.forEach((number) => print('元素: $number'));
// 函数式编程操作
var doubled = numbers.map((n) => n * 2).toList();
var evens = numbers.where((n) => n % 2 == 0).toList();
var sum = numbers.reduce((value, element) => value + element);
print('翻倍: $doubled');
print('偶数: $evens');
print('总和: $sum');
}
Set(集合)
void setExamples() {
// Set声明 - 自动去重
Set<String> countries = {'China', 'USA', 'Japan', 'China'};
print(countries); // {China, USA, Japan}
var numbers = <int>{1, 2, 3, 3, 4}; // 类型推断
print(numbers); // {1, 2, 3, 4}
// Set操作
countries.add('UK');
countries.remove('Japan');
print('包含USA: ${countries.contains('USA')}');
// 集合运算
Set<int> setA = {1, 2, 3, 4};
Set<int> setB = {3, 4, 5, 6};
print('并集: ${setA.union(setB)}'); // {1, 2, 3, 4, 5, 6}
print('交集: ${setA.intersection(setB)}'); // {3, 4}
print('差集: ${setA.difference(setB)}'); // {1, 2}
}
Map(映射)
void mapExamples() {
// Map声明
Map<String, String> capitals = {
'China': 'Beijing',
'USA': 'Washington',
'Japan': 'Tokyo',
};
var scores = <String, int>{ // 类型推断
'Alice': 95,
'Bob': 87,
'Charlie': 92,
};
// Map操作
capitals['UK'] = 'London'; // 添加键值对
capitals['Japan'] = '東京'; // 更新值
capitals.remove('USA'); // 删除键值对
print('中国首都: ${capitals['China']}');
print('包含法国: ${capitals.containsKey('France')}');
// Map遍历
capitals.forEach((key, value) {
print('$key 的首都是 $value');
});
for (var entry in capitals.entries) {
print('${entry.key}: ${entry.value}');
}
// 键和值的集合
print('所有国家: ${capitals.keys.toList()}');
print('所有首都: ${capitals.values.toList()}');
}
1.4 空安全
Dart的空安全特性帮助在编译时捕获空引用错误:
void nullSafety() {
// 不可空类型
String name = 'Dart'; // 不能为null
// name = null; // 编译错误
// 可空类型
String? nullableName; // 可以为null
nullableName = null; // 允许赋值为null
nullableName = 'Dart'; // 也可以赋值为非null
// 空安全操作符
String? maybeName;
// 安全调用操作符 ?.
int? length = maybeName?.length;
// 空值合并操作符 ??
String displayName = maybeName ?? '未知用户';
// 空断言操作符 !
String definitelyName = maybeName!; // 断言不为null
// 空安全检查
if (maybeName != null) {
// 在这个作用域内,Dart知道maybeName不为null
print(maybeName.length);
}
print('空安全示例完成');
}
2. 函数与面向对象
2.1 函数基础
Dart中的函数是一等公民,可以作为参数传递和返回值。
// 基本函数声明
int add(int a, int b) {
return a + b;
}
// 箭头函数(单行函数)
int multiply(int a, int b) => a * b;
// 可选参数函数
void userProfile(String name, [int? age, String? city]) {
print('姓名: $name');
if (age != null) print('年龄: $age');
if (city != null) print('城市: $city');
}
// 命名参数函数
void createUser({required String name, int age = 0, String? email}) {
print('创建用户: $name, $age岁');
if (email != null) print('邮箱: $email');
}
// 函数作为参数
void executeOperation(int a, int b, int Function(int, int) operation) {
var result = operation(a, b);
print('操作结果: $result');
}
void functionExamples() {
// 调用基本函数
var sum = add(5, 3);
print('5 + 3 = $sum');
// 调用箭头函数
var product = multiply(4, 7);
print('4 × 7 = $product');
// 调用可选参数函数
userProfile('Alice');
userProfile('Bob', 25);
userProfile('Charlie', 30, 'New York');
// 调用命名参数函数
createUser(name: 'David');
createUser(name: 'Eva', age: 28);
createUser(name: 'Frank', age: 35, email: 'frank@example.com');
// 传递函数作为参数
executeOperation(10, 5, add);
executeOperation(10, 5, multiply);
executeOperation(10, 5, (a, b) => a - b); // 匿名函数
}
2.2 匿名函数与高阶函数
void anonymousFunctionExamples() {
var numbers = [1, 2, 3, 4, 5];
// 匿名函数
numbers.forEach((number) {
print('数字: $number');
});
// 更简洁的匿名函数
numbers.forEach((number) => print('数值: $number'));
// 函数赋值给变量
var shout = (String message) => message.toUpperCase() + '!';
print(shout('hello dart'));
// 返回函数的函数
Function multiplier(int factor) {
return (int value) => value * factor;
}
var doubleIt = multiplier(2);
var tripleIt = multiplier(3);
print('双倍: ${doubleIt(5)}'); // 10
print('三倍: ${tripleIt(5)}'); // 15
// 函数组合
String capitalize(String text) => text[0].toUpperCase() + text.substring(1);
String addExclamation(String text) => text + '!';
var transform = (String text) => addExclamation(capitalize(text));
print(transform('hello world')); // Hello world!
}
2.3 类与对象
基础类定义
class Person {
// 实例变量
String name;
int age;
// 构造函数
Person(this.name, this.age);
// 命名构造函数
Person.newborn(String name) : this(name, 0);
// 方法
void introduce() {
print('你好,我是$name,今年$age岁');
}
// Getter
String get description => '$name ($age岁)';
// Setter
set birthday(DateTime date) {
var now = DateTime.now();
age = now.year - date.year;
}
// 重写toString方法
@override
String toString() => 'Person{name: $name, age: $age}';
}
void classExamples() {
// 创建对象
var alice = Person('Alice', 25);
var baby = Person.newborn('Baby');
// 调用方法
alice.introduce();
baby.introduce();
// 使用Getter
print(alice.description);
// 使用Setter
alice.birthday = DateTime(1998, 5, 15);
print('更新后年龄: ${alice.age}');
print(alice.toString());
}
继承与多态
// 基类
class Animal {
String name;
int age;
Animal(this.name, this.age);
void makeSound() {
print('动物发出声音');
}
void sleep() {
print('$name 在睡觉');
}
}
// 继承
class Dog extends Animal {
String breed;
Dog(String name, int age, this.breed) : super(name, age);
// 方法重写
@override
void makeSound() {
print('$name 汪汪叫!');
}
// 新增方法
void fetch() {
print('$name 在接飞盘');
}
}
class Cat extends Animal {
Cat(String name, int age) : super(name, age);
@override
void makeSound() {
print('$name 喵喵叫!');
}
void climb() {
print('$name 在爬树');
}
}
void inheritanceExamples() {
// 多态
Animal myDog = Dog('Buddy', 3, 'Golden Retriever');
Animal myCat = Cat('Whiskers', 2);
// 运行时多态
myDog.makeSound(); // Buddy 汪汪叫!
myCat.makeSound(); // Whiskers 喵喵叫!
// 类型检查和转换
if (myDog is Dog) {
(myDog as Dog).fetch(); // 类型转换后调用子类方法
}
List<Animal> animals = [myDog, myCat];
for (var animal in animals) {
animal.makeSound(); // 多态调用
}
}
抽象类与接口
// 抽象类
abstract class Shape {
// 抽象方法
double area();
double perimeter();
// 具体方法
void describe() {
print('这个形状的面积是 ${area()},周长是 ${perimeter()}');
}
}
// 实现抽象类
class Rectangle extends Shape {
double width;
double height;
Rectangle(this.width, this.height);
@override
double area() => width * height;
@override
double perimeter() => 2 * (width + height);
}
class Circle extends Shape {
double radius;
Circle(this.radius);
@override
double area() => 3.14159 * radius * radius;
@override
double perimeter() => 2 * 3.14159 * radius;
}
// 接口(在Dart中每个类都隐式定义了一个接口)
class Square implements Shape {
double side;
Square(this.side);
@override
double area() => side * side;
@override
double perimeter() => 4 * side;
@override
void describe() {
print('这个正方形的边长是 $side,面积是 ${area()}');
}
}
void abstractClassExamples() {
List<Shape> shapes = [
Rectangle(5, 3),
Circle(4),
Square(6),
];
for (var shape in shapes) {
shape.describe();
}
}
Mixin(混入)
// Mixin定义
mixin Flyable {
void fly() {
print('在空中飞翔');
}
}
mixin Swimmable {
void swim() {
print('在水中游泳');
}
}
mixin Runnable {
void run() {
print('在陆地上奔跑');
}
}
// 使用Mixin
class Bird with Flyable, Runnable {
String name;
Bird(this.name);
void describe() {
print('$name 可以:');
fly();
run();
}
}
class Duck with Flyable, Swimmable, Runnable {
String name;
Duck(this.name);
void describe() {
print('$name 可以:');
fly();
swim();
run();
}
}
void mixinExamples() {
var sparrow = Bird('麻雀');
var duck = Duck('鸭子');
sparrow.describe();
print('---');
duck.describe();
}
3. 异步编程(Future/Stream)
3.1 Future基础
Future表示一个可能在未来完成的计算或操作。
import 'dart:async';
// 模拟异步操作
Future<String> fetchUserData() {
return Future.delayed(Duration(seconds: 2), () => '用户数据加载完成');
}
Future<int> fetchUserScore() {
return Future.delayed(Duration(seconds: 1), () => 95);
}
void futureBasicExamples() async {
print('开始获取用户数据...');
// 使用then处理Future完成
fetchUserData().then((data) {
print('收到数据: $data');
}).catchError((error) {
print('发生错误: $error');
});
// 使用async/await(更推荐)
try {
var data = await fetchUserData();
print('使用await收到数据: $data');
} catch (error) {
print('发生错误: $error');
}
// 多个Future处理
var userData = fetchUserData();
var userScore = fetchUserScore();
// 等待所有Future完成
var results = await Future.wait([userData, userScore]);
print('所有结果: $results');
// Future链式操作
var processedData = await fetchUserData()
.then((data) => data.toUpperCase())
.then((data) => '处理后的: $data');
print(processedData);
}
3.2 高级Future用法
Future<String> loginUser(String username, String password) async {
await Future.delayed(Duration(seconds: 1));
if (username == 'admin' && password == '123456') {
return '登录成功';
} else {
throw Exception('用户名或密码错误');
}
}
Future<String> getUserProfile(String token) async {
await Future.delayed(Duration(seconds: 2));
return '用户资料: 姓名: 张三, 年龄: 25';
}
void advancedFutureExamples() async {
// Future.error创建错误Future
var errorFuture = Future.error(Exception('自定义错误'));
// Future.value创建立即完成的Future
var immediateFuture = Future.value('立即完成的值');
// 超时控制
try {
var result = await fetchUserData().timeout(
Duration(seconds: 1),
onTimeout: () => '请求超时,返回默认值'
);
print('超时控制结果: $result');
} catch (e) {
print('超时错误: $e');
}
// 模拟登录流程
try {
var token = await loginUser('admin', '123456');
print('登录结果: $token');
var profile = await getUserProfile(token);
print('用户资料: $profile');
} catch (e) {
print('登录失败: $e');
}
// Future微任务
print('开始');
Future(() => print('普通任务'));
Future.microtask(() => print('微任务'));
print('结束');
// 输出顺序: 开始 → 结束 → 微任务 → 普通任务
}
3.3 Stream基础
Stream表示一系列异步事件。
import 'dart:async';
// 创建Stream
Stream<int> countStream(int max) async* {
for (int i = 1; i <= max; i++) {
await Future.delayed(Duration(milliseconds: 500));
yield i; // 产生流数据
}
}
// 转换Stream
Stream<String> stringStream(int max) async* {
for (int i = 1; i <= max; i++) {
await Future.delayed(Duration(milliseconds: 300));
yield '项目 $i';
}
}
void streamBasicExamples() async {
print('开始Stream示例...');
// 监听Stream
var subscription = countStream(5).listen(
(data) => print('收到数据: $data'),
onError: (error) => print('错误: $error'),
onDone: () => print('Stream完成'),
cancelOnError: false,
);
// 等待Stream完成
await subscription.asFuture();
print('--- Stream转换 ---');
// 使用await for处理Stream
await for (var number in countStream(3)) {
print('await for: $number');
}
print('--- Stream操作 ---');
// Stream转换操作
var transformed = countStream(4)
.where((number) => number % 2 == 0) // 过滤偶数
.map((number) => number * 10) // 转换数据
.take(2); // 取前2个
await for (var value in transformed) {
print('转换后的值: $value');
}
}
3.4 高级Stream用法
class DataService {
final StreamController<String> _controller = StreamController<String>();
// 公开的Stream
Stream<String> get dataStream => _controller.stream;
// 添加数据到Stream
void addData(String data) {
_controller.add(data);
}
// 添加错误到Stream
void addError(String error) {
_controller.addError(error);
}
// 关闭Stream
void close() {
_controller.close();
}
}
void advancedStreamExamples() async {
var service = DataService();
// 广播Stream(允许多个监听器)
var broadcastStream = service.dataStream.asBroadcastStream();
// 第一个监听器
var subscription1 = broadcastStream.listen(
(data) => print('监听器1: $data'),
onError: (error) => print('监听器1错误: $error'),
onDone: () => print('监听器1: Stream关闭'),
);
// 第二个监听器
var subscription2 = broadcastStream.listen(
(data) => print('监听器2: $data'),
);
// 模拟数据产生
service.addData('第一条数据');
await Future.delayed(Duration(seconds: 1));
service.addData('第二条数据');
await Future.delayed(Duration(seconds: 1));
service.addError('模拟错误');
await Future.delayed(Duration(seconds: 1));
service.addData('最后一条数据');
// 关闭Stream
service.close();
// 取消订阅
await Future.delayed(Duration(seconds: 2));
subscription1.cancel();
subscription2.cancel();
print('--- Stream进阶操作 ---');
// Stream.reduce
var numberStream = Stream.fromIterable([1, 2, 3, 4, 5]);
var sum = await numberStream.reduce((a, b) => a + b);
print('Stream.reduce结果: $sum'); // 15
// Stream.toList
var listStream = Stream.fromIterable(['A', 'B', 'C']);
var list = await listStream.toList();
print('Stream.toList结果: $list'); // [A, B, C]
// Stream缓冲
var bufferedStream = countStream(10).bufferCount(3);
await for (var buffer in bufferedStream) {
print('缓冲数据: $buffer'); // [1,2,3], [4,5,6], [7,8,9], [10]
}
}
4. Dart特有语法糖
4.1 级联操作符(..)
级联操作符允许对同一对象执行一系列操作。
class Button {
String text = '';
String color = 'blue';
double width = 100.0;
double height = 50.0;
bool isEnabled = true;
void click() {
print('按钮被点击: $text');
}
@override
String toString() => '按钮: $text, 颜色: $color, 尺寸: ${width}x$height';
}
void cascadeNotationExamples() {
// 传统方式
var button1 = Button();
button1.text = '提交';
button1.color = 'green';
button1.width = 120.0;
button1.click();
// 使用级联操作符
var button2 = Button()
..text = '取消'
..color = 'red'
..width = 80.0
..height = 40.0
..click();
print(button1);
print(button2);
// 嵌套级联
var complexButton = Button()
..text = '复杂按钮'
..color = 'purple'
..width = 200.0
..height = 60.0
..click()
..text = '更新后的文本'
..click();
print(complexButton);
// 在列表中使用级联
var buttons = <Button>[
Button()..text = '按钮1'..color = 'blue',
Button()..text = '按钮2'..color = 'green',
Button()..text = '按钮3'..color = 'red',
];
for (var button in buttons) {
print(button);
}
}
4.2 空安全操作符
class User {
String? name;
int? age;
Address? address;
User({this.name, this.age, this.address});
}
class Address {
String? street;
String? city;
Address({this.street, this.city});
}
void nullAwareOperators() {
// ?. 安全调用操作符
User? user;
print(user?.name); // 输出: null,不会抛出异常
user = User(name: 'Alice', address: Address(street: '123 Main St'));
print(user?.name); // 输出: Alice
print(user?.address?.city); // 输出: null
// ?? 空值合并操作符
String? nullableName;
String displayName = nullableName ?? '未知用户';
print(displayName); // 输出: 未知用户
// ??= 空值赋值操作符
String? currentUser;
currentUser ??= '默认用户';
print(currentUser); // 输出: 默认用户
// ...? 空感知展开操作符
List<int>? nullableList;
List<int> combined = [1, 2, 3, ...?nullableList];
print(combined); // 输出: [1, 2, 3]
// ! 空断言操作符(谨慎使用)
User definiteUser = User(name: 'Bob')!;
print(definiteUser.name);
}
4.3 扩展方法
扩展方法允许向现有类添加新功能。
// 为int类型添加扩展
extension IntExtensions on int {
// 判断是否为偶数
bool get isEven => this % 2 == 0;
// 判断是否为奇数
bool get isOdd => this % 2 == 1;
// 转换为时间间隔
Duration get seconds => Duration(seconds: this);
Duration get minutes => Duration(minutes: this);
Duration get hours => Duration(hours: this);
// 重复执行操作
void times(Function(int) action) {
for (int i = 0; i < this; i++) {
action(i);
}
}
}
// 为String类型添加扩展
extension StringExtensions on String {
// 反转字符串
String get reversed => split('').reversed.join();
// 判断是否为电子邮件
bool get isEmail => contains('@') && contains('.');
// 转换为标题格式
String toTitleCase() {
if (isEmpty) return this;
return this[0].toUpperCase() + substring(1).toLowerCase();
}
// 解析为int,失败返回null
int? toIntOrNull() => int.tryParse(this);
}
void extensionMethodsExamples() {
// 使用int扩展
print(5.isEven); // false
print(5.isOdd); // true
print(3.times((i) => print('重复 $i 次')));
// 输出:
// 重复 0 次
// 重复 1 次
// 重复 2 次
// 使用Duration扩展
Future.delayed(2.seconds, () => print('2秒后执行'));
// 使用String扩展
print('hello'.reversed); // olleh
print('test@example.com'.isEmail); // true
print('dart language'.toTitleCase()); // Dart language
print('123'.toIntOrNull()); // 123
print('abc'.toIntOrNull()); // null
}
4.4 集合字面量与操作符
void collectionLiteralsAndOperators() {
// 集合if
var shouldIncludeExtra = true;
var items = [
'基础项目1',
'基础项目2',
if (shouldIncludeExtra) '额外项目',
];
print(items); // [基础项目1, 基础项目2, 额外项目]
// 集合for
var numbers = [1, 2, 3];
var doubledNumbers = [
for (var number in numbers) number * 2,
];
print(doubledNumbers); // [2, 4, 6]
// 展开操作符
var list1 = [1, 2, 3];
var list2 = [4, 5, 6];
var combined = [...list1, ...list2];
print(combined); // [1, 2, 3, 4, 5, 6]
// Map字面量增强
var map = {
'name': 'Alice',
'age': 25,
if (shouldIncludeExtra) 'city': 'Beijing',
for (var i in [1, 2, 3]) 'key$i': 'value$i',
};
print(map);
// {name: Alice, age: 25, city: Beijing, key1: value1, key2: value2, key3: value3}
// Set字面量增强
var set = {
1, 2, 3,
if (shouldIncludeExtra) 4,
for (var i in [1, 2]) i * 10,
};
print(set); // {1, 2, 3, 4, 10, 20}
}
4.5 其他实用语法糖
void otherSyntaxSugar() {
// 条件属性访问
String? maybeString;
print(maybeString?.length); // null
// 使用[]访问Map的简洁方式
var config = {'theme': 'dark', 'language': 'zh'};
print(config['theme']); // dark
// 函数简写
var numbers = [1, 2, 3, 4, 5];
var evens = numbers.where((n) => n.isEven); // 简写形式
print(evens); // (2, 4)
// 字符串多行和插值
var name = 'Dart';
var version = 2.12;
var message = '''
欢迎使用 $name!
当前版本: $version
下一个版本: ${version + 0.1}
''';
print(message);
// 类型测试和转换的简写
var value = 'Hello';
if (value is String) {
print(value.length); // 自动转换为String类型
}
// 使用as进行显式类型转换
(value as String).toUpperCase();
}
实战项目:简单的待办事项应用
让我们用学到的Dart知识构建一个简单的待办事项应用:
class TodoItem {
final String id;
String title;
bool isCompleted;
DateTime createdAt;
TodoItem({
required this.title,
this.isCompleted = false,
}) : id = DateTime.now().millisecondsSinceEpoch.toString(),
createdAt = DateTime.now();
void toggleComplete() {
isCompleted = !isCompleted;
}
@override
String toString() => '[${isCompleted ? '✓' : ' '}] $title';
}
class TodoManager {
final List<TodoItem> _items = [];
// 添加待办事项
void addTodo(String title) {
_items.add(TodoItem(title: title));
print('添加待办: $title');
}
// 完成待办事项
void completeTodo(String id) {
var item = _items.firstWhere((item) => item.id == id);
item.toggleComplete();
print('完成待办: ${item.title}');
}
// 删除待办事项
void removeTodo(String id) {
_items.removeWhere((item) => item.id == id);
print('删除待办');
}
// 获取所有待办事项
List<TodoItem> get todos => List.unmodifiable(_items);
// 获取未完成事项
List<TodoItem> get pendingTodos =>
_items.where((item) => !item.isCompleted).toList();
// 获取已完成事项
List<TodoItem> get completedTodos =>
_items.where((item) => item.isCompleted).toList();
// 清空所有事项
void clearAll() {
_items.clear();
print('清空所有待办事项');
}
// 显示统计信息
void showStats() {
print('''
=== 待办事项统计 ===
总计: ${_items.length}
待完成: ${pendingTodos.length}
已完成: ${completedTodos.length}
完成率: ${_items.isEmpty ? 0 : (completedTodos.length / _items.length * 100).toStringAsFixed(1)}%
===============
''');
}
}
void todoAppExample() async {
var manager = TodoManager();
print('🚀 启动待办事项应用...\n');
// 添加待办事项
manager.addTodo('学习Dart基础语法');
manager.addTodo('练习Future和Stream');
manager.addTodo('构建Flutter应用');
await Future.delayed(1.seconds);
// 显示所有事项
print('\n📋 所有待办事项:');
manager.todos.forEach(print);
await Future.delayed(1.seconds);
// 完成第一个事项
if (manager.todos.isNotEmpty) {
manager.completeTodo(manager.todos.first.id);
}
await Future.delayed(1.seconds);
// 显示统计
manager.showStats();
await Future.delayed(1.seconds);
// 显示未完成事项
print('⏳ 未完成事项:');
manager.pendingTodos.forEach(print);
await Future.delayed(1.seconds);
// 完成所有事项
print('\n🎯 批量完成所有事项...');
for (var todo in manager.pendingTodos) {
manager.completeTodo(todo.id);
await Future.delayed(500.milliseconds);
}
// 最终统计
manager.showStats();
}
void main() async {
// 运行待办事项应用示例
await todoAppExample();
print('\n✨ Dart语言快速入门学习完成!');
print('接下来可以开始学习Flutter框架了!');
}
学习资源与下一步
推荐学习路径
- 巩固Dart基础:熟练掌握本文介绍的核心概念
- 实践小项目:用Dart构建命令行工具或简单应用
- 学习Flutter:将Dart知识应用到Flutter开发中
- 深入高级特性:学习Isolate、泛型、元编程等
实用资源
常见问题解答
Q: Dart与JavaScript/TypeScript有什么区别? A: Dart是强类型语言,有更好的工具支持和性能表现,特别适合构建大型应用。
Q: 学习Dart需要什么基础? A: 如果有Java、C#、JavaScript或Python经验,学习Dart会很容易。
Q: Dart只能用于Flutter吗? A: 不,Dart也可以用于Web后端开发(使用Aqueduct等框架)和命令行工具。