Flutter 系列教程:Dart 语言快速入门 (下)

在掌握了 Dart 的基本语法后,我们将深入学习构建复杂应用的三个核心基石:函数 (Functions)、类 (Classes) 和异步编程 (Asynchronous Programming)。这部分内容对于理解 Flutter 的 Widget 结构和处理网络请求等耗时操作至关重要。

学习目标

  • 掌握如何定义和使用函数,包括各类参数。
  • 理解面向对象编程,学会创建和使用类 (Class)。
  • 初步掌握 Dart 的异步处理方式:Future, async, 和 await

1. 函数 (Functions)

函数是一段可重复使用的代码块。在 Dart 中,即使是函数也是对象,类型为 Function

基础函数定义

一个最简单的函数包含一个返回值类型、一个函数名、一对括号 () 和一个函数体 {}

dart 复制代码
// 返回值类型为 String,函数名为 greet,接收一个 String 类型的参数 name
String greet(String name) {
  return 'Hello, $name!';
}

void main() {
  // 调用函数
  var message = greet('Tom');
  print(message); // 输出: Hello, Tom!
}

提示 :如果函数不返回任何值,使用 void 作为返回类型。main() 函数就是一个典型的例子。

箭头函数 (Arrow Functions)

如果函数体只包含一个表达式,你可以使用更简洁的箭头语法 =>

dart 复制代码
// 上面的 greet 函数可以简写为:
String greet(String name) => 'Hello, $name!';

void main() {
  print(greet('Jerry')); // 输出: Hello, Jerry!
}

函数参数

Dart 提供了非常灵活的参数类型,这在构造 Flutter Widget 时极其常用。

a) 可选的位置参数 []

[] 包裹的参数是可选的。

dart 复制代码
String say(String from, String msg, [String? device]) {
  var result = '$from says $msg';
  // 如果 device 不为 null,则将其拼接到结果中
  if (device != null) {
    result = '$result on a $device';
  }
  return result;
}

void main() {
  print(say('John', 'Hello')); // 输出: John says Hello
  print(say('Jane', 'Hi', 'iPhone')); // 输出: Jane says Hi on a iPhone
}

b) 可选的命名参数 {} (Flutter 中最常用)

{} 包裹的参数是可选的命名参数。调用时必须指定参数名,这让代码可读性变得非常高。

dart 复制代码
// enable 和 port 都是可选的命名参数
void setup({bool enable = false, int port = 8080}) {
  print('Setup complete. Enable: $enable, Port: $port');
}

void main() {
  setup(); // 使用默认值。输出: Setup complete. Enable: false, Port: 8080
  setup(enable: true); // 指定 enable 参数。输出: Setup complete. Enable: true, Port: 8080
  setup(port: 9000, enable: true); // 指定所有参数,顺序无关。输出: Setup complete. Enable: true, Port: 9000
}

在 Flutter 中,几乎所有 Widget 的构造函数都使用了命名参数,例如 Text('Hi', style: TextStyle(color: Colors.red))


2. 类 (Classes)

类是创建对象的蓝图。在 Flutter 中,你看到的每一个界面元素,比如 Text, Button, Container,本质上都是一个类。

定义一个类

一个基础的类包含属性 (Properties/Fields)方法 (Methods)

dart 复制代码
class Person {
  // 属性 (实例变量)
  String name;
  int age;

  // 构造函数:用于创建类的实例 (对象)
  // this.name 是一个语法糖,等同于 this.name = name;
  Person(this.name, this.age);

  // 方法
  void introduce() {
    print('Hi, my name is $name and I am $age years old.');
  }
}

void main() {
  // 创建 Person 类的实例 (或称为 "对象")
  var person1 = Person('David', 30);
  var person2 = Person('Sarah', 25);

  // 调用对象的方法
  person1.introduce(); // 输出: Hi, my name is David and I am 30 years old.
  person2.introduce(); // 输出: Hi, my name is Sarah and I am 25 years old.
}

继承 (Inheritance)

继承允许一个类 (子类) 获取另一个类 (父类) 的属性和方法。这在 Flutter 中至关重要,我们自定义的 Widget 通常都需要继承 StatelessWidgetStatefulWidget

dart 复制代码
// 定义一个父类
class Animal {
  void eat() {
    print('The animal is eating.');
  }
}

// Dog 类继承自 Animal 类
class Dog extends Animal {
  void bark() {
    print('Woof woof!');
  }
}

void main() {
  var myDog = Dog();
  myDog.eat();  // 调用从父类继承来的方法
  myDog.bark(); // 调用自己的方法
}

3. 异步编程 (Future, async, await)

在 App 开发中,很多操作都是耗时的,比如从网络获取数据、读写手机文件。如果这些操作在主线程上执行,会造成界面卡顿,用户体验极差。Dart 使用 Future 对象和 async/await 关键字来优雅地处理这些异步操作。

  • Future : 一个 Future 对象代表一个未来某个时刻会产生的结果。它有点像一张"承诺书",承诺在未来会给你一个值 (或一个错误)。
  • async : 这个关键字用在函数声明上,表示这个函数是一个异步函数,它的返回值会被自动包装成一个 Future
  • await : 这个关键字必须用在 async 函数内部,它会"等待"一个 Future 完成,并返回其结果。在等待期间,它不会阻塞主线程,UI 依然可以响应用户操作。

示例:模拟网络请求

让我们模拟一个需要 2 秒才能返回数据的网络请求。

dart 复制代码
import 'dart:async'; // 需要引入 'dart:async' 库来使用 Future

// 这是一个异步函数,它返回一个将在未来完成的 String
Future<String> fetchUserData() {
  // Future.delayed 模拟了一个耗时操作
  return Future.delayed(const Duration(seconds: 2), () => 'John Doe');
}

// 异步函数必须用 async 标记
void main() async {
  print('Fetching user data...');
  
  // 使用 await 等待 fetchUserData() 这个 Future 完成
  // 在这两秒内,程序不会卡死
  String userData = await fetchUserData();
  
  // 等待结束后,才会执行下面的代码
  print('Data fetched: $userData');
  print('Program finished.');
}

运行结果:

erlang 复制代码
Fetching user data...
(等待 2 秒)
Data fetched: John Doe
Program finished.

如果没有 awaitprint(fetchUserData()) 只会打印出 Instance of 'Future<String>',而不是我们想要的结果 "John Doe"。await 就像是帮你把 Future 这个"包裹"拆开,取出里面的东西。

完整可运行代码示例

您可以像之前一样,将以下完整代码复制到 DartPad 或您的 main.dart 文件中运行,来亲自体验这些概念。

dart 复制代码
import 'dart:async';

// 1. 函数 (Function)
// 使用命名参数的函数
void printUserInfo({required String name, int age = 20}) {
  print('User: $name, Age: $age');
}

// 2. 类 (Class)
class Greeter {
  final String name; // final 属性,只能在构造时赋值

  // 构造函数
  Greeter(this.name);

  // 方法
  void sayHello() {
    print('Hello from $name!');
  }
}

// 3. 异步编程 (Async)
// 模拟一个耗时 2 秒的下载任务
Future<String> downloadFile() {
  return Future.delayed(const Duration(seconds: 2), () {
    return "Download complete!";
  });
}

// 主函数 main 必须是 async 才能使用 await
void main() async {
  print('--- 函数演示 ---');
  printUserInfo(name: 'Alice');
  printUserInfo(name: 'Bob', age: 35);
  
  print('\n--- 类和对象演示 ---');
  var greeter = Greeter('Dart');
  greeter.sayHello();

  print('\n--- 异步编程演示 ---');
  print('Starting file download...');
  
  // await 会暂停 main 函数的执行,但不会阻塞整个程序
  // 它会等待 downloadFile() 这个 Future 完成
  String result = await downloadFile(); 
  
  // Future 完成后,await 返回结果,代码继续执行
  print(result);
  
  print('Main function finished.');
}

总结与展望

恭喜!您已经完成了 Dart 语言核心部分的快速入门。我们学习了:

  • 函数的定义、箭头语法和灵活的参数(尤其是命名参数)。
  • 的定义、构造函数、属性、方法和继承。
  • 异步编程 的核心 Futureasyncawait,这是开发流畅应用的关键。

现在,您已经具备了阅读和编写大部分 Flutter 代码所需的 Dart 语言基础。从下一篇教程开始,我们将正式回归 Flutter,利用今天学到的知识,深入探索 Flutter 的核心概念:Widget

相关推荐
我是天龙_绍2 小时前
vue2数据响应式
前端
西瓜啵啵奶茶3 小时前
Siderbar和Navbar
前端
银安3 小时前
初识前端工程化
前端
银安3 小时前
前端工程化的发展——2012 前后 Grunt / Gulp 任务流
前端
鹏多多3 小时前
React跨组件数据共享useContext详解和案例
前端·javascript·react.js
linux kernel3 小时前
第一部分:HTML
前端·html
zhifanxu3 小时前
Flutter 中使用 Color 的最优方案
flutter
excel4 小时前
基于两台服务器的蓝绿切换实现零下线更新
前端
江城开朗的豌豆4 小时前
React生命周期:从诞生到更新的完整旅程
前端·javascript·react.js