一、Dart语言概述:为什么选择Dart?
在学习Flutter之前,我们必须先掌握其编程语言------Dart。让我们了解一下为什么Flutter选择Dart作为开发语言:
Dart的四大优势
-
面向对象:一切皆对象,完全的OOP语言
-
强类型:支持类型推断,兼具灵活性和安全性
-
AOT/JIT编译:开发时JIT热重载,发布时AOT高性能
-
单线程+异步:基于事件循环的异步模型,避免阻塞
Dart vs 其他语言
text
复制
下载
JavaScript - 解释型,弱类型,浏览器端
Java/Kotlin - AOT编译,强类型,Android原生
Swift - AOT编译,强类型,iOS原生
Dart - 兼具JIT/AOT,强类型,跨平台
二、Dart开发环境搭建
2.1 在线DartPad(快速体验)
访问 DartPad,无需安装即可编写Dart代码。
2.2 本地环境(推荐)
bash
复制
下载
# 如果你已经安装了Flutter,Dart已包含在内
# 可以单独安装Dart SDK
# macOS/Linux
brew tap dart-lang/dart
brew install dart
# Windows
# 从 https://dart.dev/get-dart 下载安装包
2.3 第一个Dart程序
在VS Code中创建 hello.dart:
dart
复制
下载
void main() {
print('Hello, Dart!');
print('当前时间: ${DateTime.now()}');
}
// 运行方法:
// 1. 终端:dart hello.dart
// 2. VS Code:右键 -> Run Code
三、Dart基础语法精讲
3.1 变量与常量
dart
复制
下载
// 变量声明 - 四种方式
void variablesDemo() {
// 1. var - 类型推断(推荐)
var name = '张三';
var age = 25;
var height = 1.75;
// 2. 明确类型声明
String school = '清华大学';
int score = 95;
double weight = 65.5;
bool isStudent = true;
// 3. dynamic - 动态类型(谨慎使用)
dynamic dynamicValue = '我是字符串';
dynamicValue = 100; // 可以重新赋值为数字
dynamicValue = true; // 可以重新赋值为布尔值
// 4. Object - 所有类的基类
Object objectValue = '我也是字符串';
objectValue = 200; // 可以重新赋值
// 常量声明
// final - 运行时常量
final currentTime = DateTime.now();
final List<String> hobbies = ['篮球', '音乐', '编程'];
// const - 编译时常量
const PI = 3.14159;
const MAX_SIZE = 100;
const List<int> numbers = [1, 2, 3, 4, 5];
print('''
变量示例:
姓名: $name
年龄: $age岁
BMI: ${weight / (height * height)}
是否学生: $isStudent
圆周率: $PI
''');
}
3.2 数据类型详解
dart
复制
下载
void dataTypesDemo() {
// 1. 数字类型
int integer = 42; // 整数
double floating = 3.14; // 浮点数
num number = 10; // num可以是int或double
number = 10.5;
// 数字操作
print('数字运算:');
print('5 + 3 = ${5 + 3}');
print('5 - 3 = ${5 - 3}');
print('5 * 3 = ${5 * 3}');
print('5 / 3 = ${5 / 3}'); // 结果是double
print('5 ~/ 3 = ${5 ~/ 3}'); // 整除,结果是int
print('5 % 3 = ${5 % 3}'); // 取余
// 2. 字符串
String str1 = '单引号字符串';
String str2 = "双引号字符串";
String str3 = '''
多行
字符串
示例
''';
// 字符串插值
String name = '李四';
int score = 98;
String message = '学生$name的分数是${score + 2}分';
print(message);
// 3. 布尔类型
bool isTrue = true;
bool isFalse = false;
bool result = (5 > 3) && (10 < 20);
// 4. 列表(数组)
List<String> fruits = ['苹果', '香蕉', '橙子'];
fruits.add('葡萄'); // 添加元素
fruits.remove('香蕉'); // 删除元素
// 列表遍历
print('水果列表:');
for (var fruit in fruits) {
print('- $fruit');
}
// 5. 集合(去重)
Set<int> numbers = {1, 2, 3, 3, 4}; // {1, 2, 3, 4}
numbers.add(5);
numbers.add(3); // 不会重复添加
// 6. 映射(字典/对象)
Map<String, dynamic> person = {
'name': '王五',
'age': 30,
'isMarried': false,
'hobbies': ['读书', '旅行']
};
print('个人信息:');
print('姓名: ${person['name']}');
print('爱好: ${person['hobbies']}');
// 7. Runes(Unicode字符)
String heart = '\u2665';
String smile = '\u{1f600}';
print('特殊字符: $heart $smile');
}
3.3 控制流程
dart
复制
下载
void controlFlowDemo() {
int score = 85;
// 1. if-else
print('成绩评定:');
if (score >= 90) {
print('优秀');
} else if (score >= 80) {
print('良好'); // 输出这个
} else if (score >= 60) {
print('及格');
} else {
print('不及格');
}
// 2. for循环
print('\nfor循环:');
for (int i = 1; i <= 5; i++) {
print('第$i次循环');
}
// 3. for-in循环
List<String> colors = ['红', '绿', '蓝'];
for (var color in colors) {
print('颜色: $color');
}
// 4. forEach循环
print('\nforEach:');
colors.forEach((color) {
print('颜色: $color');
});
// 5. while循环
print('\nwhile循环:');
int count = 0;
while (count < 3) {
print('count = $count');
count++;
}
// 6. do-while循环
print('\ndo-while循环:');
int i = 0;
do {
print('i = $i');
i++;
} while (i < 3);
// 7. switch-case
String grade = 'B';
print('\nswitch-case:');
switch (grade) {
case 'A':
print('优秀');
break;
case 'B':
print('良好'); // 输出这个
break;
case 'C':
print('中等');
break;
default:
print('其他');
}
}
四、函数:Dart的核心特性
4.1 函数基础
dart
复制
下载
// 1. 基本函数
int add(int a, int b) {
return a + b;
}
// 2. 箭头函数(单行表达式)
int multiply(int a, int b) => a * b;
// 3. 可选位置参数
String introduce(String name, [int? age, String? city]) {
String result = '我是$name';
if (age != null) result += ',今年$age岁';
if (city != null) result += ',来自$city';
return result;
}
// 4. 可选命名参数
void printPerson({String? name, int? age, bool isStudent = false}) {
print('姓名: $name, 年龄: $age, 学生: $isStudent');
}
// 5. 混合参数
void mixedParams(String required, [int? optionalPos], {String? optionalNamed}) {
print('必需: $required, 可选位置: $optionalPos, 可选命名: $optionalNamed');
}
// 6. 函数作为参数
void processNumbers(List<int> numbers, int Function(int) processor) {
for (var number in numbers) {
var result = processor(number);
print('处理结果: $result');
}
}
void functionsDemo() {
// 调用函数
print('5 + 3 = ${add(5, 3)}');
print('5 × 3 = ${multiply(5, 3)}');
// 可选参数调用
print(introduce('张三'));
print(introduce('李四', 25));
print(introduce('王五', 30, '北京'));
// 命名参数调用
printPerson(name: '赵六', age: 28);
printPerson(age: 22, name: '钱七');
printPerson(isStudent: true, name: '孙八');
// 函数作为参数
processNumbers([1, 2, 3, 4, 5], (n) => n * n);
// 匿名函数
var sayHello = (String name) {
return 'Hello, $name!';
};
print(sayHello('Dart'));
}
4.2 高阶函数应用
dart
复制
下载
void higherOrderFunctions() {
List<int> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// 1. map - 转换
var squared = numbers.map((n) => n * n).toList();
print('平方: $squared');
// 2. where - 过滤
var evens = numbers.where((n) => n % 2 == 0).toList();
print('偶数: $evens');
// 3. reduce - 累积
var sum = numbers.reduce((value, element) => value + element);
print('总和: $sum');
// 4. fold - 带初始值的累积
var product = numbers.fold(1, (value, element) => value * element);
print('乘积: $product');
// 5. forEach - 遍历
print('遍历输出:');
numbers.forEach((n) => print('数字: $n'));
// 6. any - 是否有满足条件的
bool hasLargeNumber = numbers.any((n) => n > 8);
print('是否有大于8的数: $hasLargeNumber');
// 7. every - 是否都满足条件
bool allPositive = numbers.every((n) => n > 0);
print('是否都大于0: $allPositive');
}
五、面向对象编程
5.1 类与对象
dart
复制
下载
// 1. 基础类定义
class Person {
// 属性
String name;
int age;
// 构造函数
Person(this.name, this.age);
// 命名构造函数
Person.student(this.name, this.age, this.grade);
// Getter
String get description => '$name,$age岁';
// Setter
set updateAge(int newAge) {
if (newAge > 0) {
age = newAge;
}
}
// 方法
void introduce() {
print('大家好,我是$name,今年$age岁');
}
// 重写toString
@override
String toString() {
return 'Person{name: $name, age: $age}';
}
}
// 2. 继承
class Student extends Person {
String studentId;
double score;
Student(String name, int age, this.studentId, this.score)
: super(name, age);
// 重写父类方法
@override
void introduce() {
super.introduce(); // 调用父类方法
print('我的学号是$studentId,成绩是$score分');
}
// 添加新方法
void study() {
print('$name正在学习...');
}
}
// 3. 抽象类
abstract class Animal {
String name;
Animal(this.name);
// 抽象方法
void makeSound();
// 具体方法
void sleep() {
print('$name正在睡觉');
}
}
class Dog extends Animal {
Dog(String name) : super(name);
@override
void makeSound() {
print('$name: 汪汪汪!');
}
}
// 4. 混入(Mixin)
mixin Swimmer {
void swim() {
print('正在游泳');
}
}
mixin Flyer {
void fly() {
print('正在飞翔');
}
}
class Duck with Swimmer, Flyer {
String name = '鸭子';
}
// 5. 接口(隐式)
class Car {
void drive() {
print('汽车在行驶');
}
}
class ElectricCar implements Car {
@override
void drive() {
print('电动汽车在静音行驶');
}
}
void oopDemo() {
// 创建对象
var person = Person('张三', 25);
person.introduce();
print(person.description);
// 学生对象
var student = Student('李四', 20, '2023001', 95.5);
student.introduce();
student.study();
// 动物对象
var dog = Dog('旺财');
dog.makeSound();
dog.sleep();
// 混入对象
var duck = Duck();
duck.swim();
duck.fly();
// 接口对象
var car = ElectricCar();
car.drive();
}
5.2 工厂构造函数与单例模式
dart
复制
下载
class Database {
static Database? _instance;
// 私有构造函数
Database._internal() {
print('数据库连接已建立');
}
// 工厂构造函数 - 单例模式
factory Database() {
_instance ??= Database._internal();
return _instance!;
}
void query(String sql) {
print('执行查询: $sql');
}
}
void singletonDemo() {
var db1 = Database();
var db2 = Database();
print('db1和db2是同一个实例: ${identical(db1, db2)}');
db1.query('SELECT * FROM users');
}
六、异步编程(Flutter开发核心)
6.1 Future基础
dart
复制
下载
import 'dart:async';
void futureDemo() async {
print('程序开始');
// 1. 基本Future
Future.delayed(Duration(seconds: 2), () {
print('2秒后执行');
});
// 2. Future的链式调用
fetchUserData()
.then((data) {
print('获取到数据: $data');
return processData(data);
})
.then((processedData) {
print('处理后的数据: $processedData');
})
.catchError((error) {
print('发生错误: $error');
})
.whenComplete(() {
print('操作完成');
});
// 3. async/await(推荐)
try {
print('开始异步任务');
String data = await fetchUserData();
String result = await processData(data);
print('async/await结果: $result');
} catch (e) {
print('捕获错误: $e');
}
print('程序继续执行'); // 这行会立即执行
}
Future<String> fetchUserData() {
return Future.delayed(Duration(seconds: 1), () {
// 模拟网络请求
return '用户数据JSON';
});
}
Future<String> processData(String data) {
return Future.delayed(Duration(milliseconds: 500), () {
return '处理后的$data';
});
}
6.2 Stream数据流
dart
复制
下载
void streamDemo() async {
print('Stream示例开始');
// 1. 创建Stream
Stream<int> numberStream = Stream.fromIterable([1, 2, 3, 4, 5]);
// 2. 监听Stream
numberStream.listen(
(number) {
print('接收到数字: $number');
},
onError: (error) {
print('发生错误: $error');
},
onDone: () {
print('Stream完成');
},
cancelOnError: false,
);
// 3. async* 生成器
Stream<int> countStream(int max) async* {
for (int i = 1; i <= max; i++) {
await Future.delayed(Duration(milliseconds: 300));
yield i; // 产生数据
}
}
// 4. 使用await for处理Stream
print('开始计数:');
await for (var number in countStream(5)) {
print('计数: $number');
}
print('计数完成');
// 5. Stream常用操作
var transformedStream = countStream(3)
.map((n) => n * 2) // 转换
.where((n) => n > 3) // 过滤
.take(2); // 限制数量
print('转换后的Stream:');
await for (var n in transformedStream) {
print('结果: $n');
}
}
七、空安全与最新特性
7.1 空安全(Null Safety)
dart
复制
下载
void nullSafetyDemo() {
// 非空类型(编译时检查)
String name = '张三'; // 不能为null
// name = null; // 编译错误
// 可空类型
String? nullableName = null; // 可以为null
nullableName = '李四'; // 也可以赋值
// 空安全操作符
String? possibleName;
// 1. 条件访问
int? length = possibleName?.length;
print('长度: $length'); // null
// 2. 空合并运算符 ??
String safeName = possibleName ?? '默认名字';
print('安全名字: $safeName'); // 默认名字
// 3. 空断言操作符 !
String definitelyName = nullableName!; // 确保不为null
print('确定的名字: $definitelyName');
// 4. late关键字(延迟初始化)
late String lateName;
lateName = '延迟初始化'; // 必须在使用前初始化
print('late名字: $lateName');
// 5. required参数
void printInfo({required String name, required int age}) {
print('$name, $age岁');
}
printInfo(name: '王五', age: 30);
}
7.2 最新特性(Dart 3.0+)
dart
复制
下载
void dart3Features() {
// 1. 模式匹配(Pattern Matching)
var numbers = [1, 2, 3];
// 列表模式
var [x, y, z] = numbers;
print('解构: $x, $y, $z');
// 2. switch表达式增强
var status = 'success';
var message = switch (status) {
'success' => '操作成功',
'error' => '操作失败',
'loading' => '加载中...',
_ => '未知状态',
};
print('状态: $message');
// 3. 密封类(Sealed Class)
var shape = Shape.circle(radius: 5);
var area = switch (shape) {
Circle(radius: var r) => 3.14 * r * r,
Square(side: var s) => s * s,
Rectangle(width: var w, height: var h) => w * h,
};
print('面积: $area');
}
// 密封类示例
sealed class Shape {}
class Circle extends Shape {
final double radius;
Circle({required this.radius});
}
class Square extends Shape {
final double side;
Square({required this.side});
}
class Rectangle extends Shape {
final double width;
final double height;
Rectangle({required this.width, required this.height});
}
八、Flutter中Dart最佳实践
dart
复制
下载
// 1. 使用const构造函数
class FlutterWidget {
final String title;
final int count;
const FlutterWidget(this.title, this.count);
}
// 2. 扩展方法
extension StringExtension on String {
bool get isEmail {
return RegExp(r'^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$').hasMatch(this);
}
String get capitalize {
if (isEmpty) return this;
return this[0].toUpperCase() + substring(1);
}
}
// 3. 使用mixin复用代码
mixin ValidationMixin {
bool isValidEmail(String email) => email.isEmail;
bool isValidPassword(String password) => password.length >= 6;
}
class LoginForm with ValidationMixin {
void submit(String email, String password) {
if (isValidEmail(email) && isValidPassword(password)) {
print('登录成功');
} else {
print('输入无效');
}
}
}
void flutterBestPractices() {
// 使用const创建对象
const widget = FlutterWidget('标题', 10);
// 使用扩展方法
String email = 'test@example.com';
print('邮箱有效: ${email.isEmail}');
print('首字母大写: ${'hello'.capitalize}');
// 使用mixin
var form = LoginForm();
form.submit('user@test.com', '123456');
}
九、实战练习:学生成绩管理系统
dart
复制
下载
import 'dart:io';
class Student {
final String id;
final String name;
final Map<String, double> scores;
Student(this.id, this.name, this.scores);
double get averageScore {
if (scores.isEmpty) return 0;
return scores.values.reduce((a, b) => a + b) / scores.length;
}
void display() {
print('学号: $id, 姓名: $name');
scores.forEach((subject, score) {
print(' $subject: $score分');
});
print(' 平均分: ${averageScore.toStringAsFixed(1)}');
}
}
class GradeManager {
final List<Student> students = [];
void addStudent() {
print('请输入学号:');
var id = stdin.readLineSync()!;
print('请输入姓名:');
var name = stdin.readLineSync()!;
var scores = <String, double>{};
var moreSubjects = true;
while (moreSubjects) {
print('请输入科目名称 (输入q结束):');
var subject = stdin.readLineSync()!;
if (subject.toLowerCase() == 'q') {
moreSubjects = false;
continue;
}
print('请输入$subject成绩:');
var score = double.parse(stdin.readLineSync()!);
scores[subject] = score;
}
students.add(Student(id, name, scores));
print('学生添加成功!');
}
void showAllStudents() {
if (students.isEmpty) {
print('暂无学生数据');
return;
}
print('\n=== 所有学生成绩 ===');
for (var student in students) {
student.display();
print('---');
}
}
void findTopStudent() {
if (students.isEmpty) {
print('暂无学生数据');
return;
}
var topStudent = students.reduce((a, b) =>
a.averageScore > b.averageScore ? a : b);
print('\n=== 最高分学生 ===');
topStudent.display();
}
Future<void> saveToFile() async {
var file = File('students.txt');
var sink = file.openWrite();
for (var student in students) {
sink.write('${student.id},${student.name}');
student.scores.forEach((subject, score) {
sink.write(',$subject:$score');
});
sink.writeln();
}
await sink.close();
print('数据已保存到文件');
}
}
void runGradeManager() async {
var manager = GradeManager();
var running = true;
while (running) {
print('\n=== 学生成绩管理系统 ===');
print('1. 添加学生');
print('2. 显示所有学生');
print('3. 查找最高分学生');
print('4. 保存到文件');
print('5. 退出');
print('请选择操作 (1-5):');
var choice = stdin.readLineSync();
switch (choice) {
case '1':
manager.addStudent();
break;
case '2':
manager.showAllStudents();
break;
case '3':
manager.findTopStudent();
break;
case '4':
await manager.saveToFile();
break;
case '5':
running = false;
print('感谢使用,再见!');
break;
default:
print('无效选择,请重新输入');
}
}
}
void main() async {
print('=== Dart语言实战:学生成绩管理系统 ===');
await runGradeManager();
}