【Flutter入门】2. 快速掌握Dart语言 - 从 Java、JavaScript 转型必看

写在前面

作为 Flutter 开发的基础语言,Dart 融合了 Java 的类型安全和 JavaScript 的灵活性。如果您已经掌握了 Java 或 JavaScript,那么学习 Dart 将会非常轻松。本文将通过实例和对比的方式,帮助您快速掌握 Dart 的核心特性。

为什么选择 Dart?

在开始学习之前,让我们先了解为什么要选择 Dart:

  1. 优秀的类型系统

    • 支持静态类型检查
    • 类型推断让代码更简洁
    • 空安全特性避免空指针异常
  2. 现代化的语言特性

    • 支持异步编程(async/await)
    • 强大的集合操作 API
    • Mixin 和扩展方法支持
  3. 跨平台能力

    • Web 开发(编译成 JavaScript)
    • 移动应用开发(通过 Flutter)
    • 服务端开发

变量和数据类型

Dart 是一种静态类型语言,支持显式类型声明和类型推断。以下是几种常见的变量声明方式:

1. 变量声明的不同方式

  • 显式类型声明:明确指定变量的类型。

    dart 复制代码
    String name = 'Flutter'; // 显式声明为 String 类型
  • 类型推断 :使用 var 关键字,编译器会根据赋值自动推断类型。

    dart 复制代码
    var age = 25; // 推断为 int 类型
  • 动态类型 :使用 dynamic 关键字,允许变量在运行时改变类型。

    dart 复制代码
    dynamic height = 1.75; // 动态类型,可以随时改变类型
    height = "tall"; // 运行时可以改变类型
  • 常量 :使用 finalconst 关键字声明不可变的变量。

    dart 复制代码
    final version = '3.0.0'; // 运行时常量,只能赋值一次
    const PI = 3.14159; // 编译时常量,必须在编译时确定

2. 类型推断的使用场景

  • 集合类型 :Dart 支持多种集合类型,如 ListMap,并且可以通过类型推断简化声明。

    dart 复制代码
    var list = ['a', 'b', 'c']; // List<String>
    var map = {1: 'one', 2: 'two'}; // Map<int, String>

3. 类型安全的重要性

Dart 是强类型语言,确保代码的类型安全非常重要。例如:

dart 复制代码
void example() {
  var name = 'Flutter';
  // name = 42; // 编译错误:不能将 int 赋值给 String 类型的变量
}

空安全特性

Dart 引入了空安全(Null Safety),以防止空指针异常。以下是几种处理可空类型的常见方法:

1. 可空类型

  • 使用 ? 表示变量可以为 null

    dart 复制代码
    String? nullableName;
    int? age;

2. 延迟初始化

  • 使用 late 关键字延迟初始化变量,确保在首次访问时才进行初始化。

    dart 复制代码
    late String name;

    注意:延迟初始化变量必须在声明时提供默认值,否则会报错。

3. 空值检查

  • 使用 ?? 运算符提供默认值。

    dart 复制代码
    void printName(String? name) {
      print(name ?? 'Unknown'); // 如果 name 为 null,则输出 'Unknown'
    }
  • 使用 ?. 安全调用操作符。

    dart 复制代码
    print(name?.toUpperCase()); // 如果 name 为 null,则不会调用 toUpperCase()
  • 使用 ! 断言非空。

    dart 复制代码
    if (name != null) {
      print(name!.toUpperCase()); // 断言 name 不为 null
    }

4. 应用示例

dart 复制代码
// 实际应用场景示例
class User {
  final String name;
  final int? age; // 可选年龄
  late final String email; // 延迟初始化邮箱

  User(this.name, {this.age}) {
    // 延迟初始化示例
    email = fetchEmailFromDatabase(); // 从数据库获取邮箱
  }

  // 空安全处理示例
  String getDisplayName() {
    return age != null ? '$name ($age岁)' : name;
  }
}

函数定义

Dart 支持多种函数定义方式,包括普通函数、箭头函数、带参数的函数等。

1. 基本函数

  • 返回一个整数的简单加法函数。

    dart 复制代码
    int add(int a, int b) {
      return a + b;
    }

2. 箭头函数

  • 简洁的单行函数定义。

    dart 复制代码
    void printHello() => print('Hello');

3. 可选参数

  • 使用方括号 [ ] 定义可选参数,默认值可以用 ?? 提供。

    dart 复制代码
    String sayHello([String? name]) {
      return 'Hello ${name ?? "Guest"}'; // 如果 name 为 null,则使用 "Guest"
    }

4. 命名参数

  • 使用花括号 { } 定义命名参数,默认值可以用 ?? 提供。

    dart 复制代码
    String greet({String name = 'Guest', int age = 0}) {
      return 'Hello $name, you are $age years old.';
    }

异步编程进阶

Dart 支持异步编程,通过 FutureStream 实现非阻塞操作。

1. Future 使用

  • 使用 asyncawait 关键字简化异步代码。

    dart 复制代码
    Future<String> fetchUserData() async {
      try {
        final response = await dio.get('/api/user');
        return response.data['name'];
      } catch (e) {
        return 'Error: $e';
      }
    }

2. Stream 使用

  • 使用 async*yield 创建流。

    dart 复制代码
    Stream<int> countStream(int max) async* {
      for (int i = 1; i <= max; i++) {
        await Future.delayed(Duration(seconds: 1));
        yield i;
      }
    }

3. 使用 StreamBuilder

  • 在 Flutter 中使用 StreamBuilder 构建响应式 UI。

    dart 复制代码
    StreamBuilder<int>(
      stream: countStream(10),
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          return Text('Count: ${snapshot.data}');
        }
        return CircularProgressIndicator();
      },
    )

4. 实际网络请求示例

dart 复制代码
// 实际网络请求示例
Future<List<User>> fetchUsers() async {
  try {
    final response = await http.get(Uri.parse('https://api.example.com/users'));
    if (response.statusCode == 200) {
      final List<dynamic> data = jsonDecode(response.body);
      return data.map((json) => User.fromJson(json)).toList();
    } else {
      throw Exception('加载用户数据失败');
    }
  } catch (e) {
    print('错误:$e');
    return [];
  }
}

// Stream 实际应用示例
Stream<int> countdown(int seconds) async* {
  for (var i = seconds; i >= 0; i--) {
    await Future.delayed(Duration(seconds: 1));
    yield i;
  }
}

// 使用示例
void main() async {
  await for (final count in countdown(5)) {
    print('倒计时:$count');
  }
  print('完成!');
}

Mixin 和扩展

Dart 支持 Mixin 和扩展方法,用于增强类的功能。

1. Mixin 定义

  • Mixin 是一种组合类功能的方式,类似于多继承。

    dart 复制代码
    mixin Logger {
      void log(String message) {
        print('LOG: $message');
      }
    }
    
    class UserService with Logger {
      void createUser() {
        log('Creating user...');
        // 创建用户逻辑
      }
    }

2. 扩展方法

  • 扩展方法允许为现有类添加新方法,而无需修改其源代码。

    dart 复制代码
    extension StringExtension on String {
      String capitalize() {
        return "${this[0].toUpperCase()}${this.substring(1)}";
      }
    }
    
    void main() {
      print('hello'.capitalize()); // 输出: Hello
    }

与 Java/JavaScript 的对比

Dart 融合了 Java 的静态类型特性和 JavaScript 的灵活性,下面是主要区别:

1. 变量声明对比

dart 复制代码
// Dart
var name = 'Flutter';
String title = 'Hello';
dynamic value = 42;

// Java
String name = "Java";
var title = "Hello"; // Java 10+ 支持
Object value = 42;

// JavaScript
let name = 'JavaScript';
const title = 'Hello';
var value = 42;

2. 函数定义对比

dart 复制代码
// Dart
void hello(String name) => print('Hello $name');
int add(int a, {int b = 0}) => a + b;

// Java
public void hello(String name) {
    System.out.println("Hello " + name);
}
public int add(int a, int b) {
    return a + b;
}

// JavaScript
const hello = (name) => console.log(`Hello ${name}`);
const add = (a, b = 0) => a + b;

3. 类定义对比

dart 复制代码
// Dart
class Person {
  final String name;
  int? age;

  Person(this.name, {this.age}); // 简洁的构造函数

  void sayHello() => print('Hello, I am $name');
}

// Java
public class Person {
    private final String name;
    private Integer age;

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public void sayHello() {
        System.out.println("Hello, I am " + name);
    }
}

// JavaScript
class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }

    sayHello() {
        console.log(`Hello, I am ${this.name}`);
    }
}

4. 异步编程对比

dart 复制代码
// Dart
Future<String> fetchData() async {
  await Future.delayed(Duration(seconds: 1));
  return 'Data';
}

// Java (使用 CompletableFuture)
CompletableFuture<String> fetchData() {
    return CompletableFuture.supplyAsync(() -> {
        Thread.sleep(1000);
        return "Data";
    });
}

// JavaScript
async function fetchData() {
    await new Promise(resolve => setTimeout(resolve, 1000));
    return 'Data';
}

5. 主要特性对比

特性 Dart Java JavaScript
类型系统 静态类型(支持类型推断) 静态类型 动态类型
空安全 内置支持 需要注解(@Nullable) 无内置支持
函数式编程 支持 部分支持(Java 8+) 完全支持
异步编程 async/await CompletableFuture async/await
混入(Mixin) 支持 不支持 部分支持

6. 集合操作对比

dart 复制代码
// Dart
final list = [1, 2, 3];
final doubled = list.map((e) => e * 2).toList();
final sum = list.reduce((a, b) => a + b);

// Java
List<Integer> list = Arrays.asList(1, 2, 3);
List<Integer> doubled = list.stream()
    .map(e -> e * 2)
    .collect(Collectors.toList());
int sum = list.stream().reduce(0, Integer::sum);

// JavaScript
const list = [1, 2, 3];
const doubled = list.map(e => e * 2);
const sum = list.reduce((a, b) => a + b);

实战技巧

在实际开发中,以下是一些常用的 Dart 编程技巧:

1. 字符串处理技巧

dart 复制代码
// 1. 字符串模板使用
final name = 'Dart';
print('Hello $name'); // 简单变量
print('1 + 1 = ${1 + 1}'); // 表达式

// 2. 多行字符串
final multiLine = '''
  这是第一行
  这是第二行
  这是第三行
''';

// 3. 字符串拼接优化
final items = ['A', 'B', 'C'];
// ❌ 不推荐
String result = '';
for (var item in items) {
  result += item + ', ';
}

// ✅ 推荐
final result = items.join(', ');

2. 集合操作技巧

dart 复制代码
// 1. 级联操作符
final button = Button()
  ..color = Colors.blue
  ..width = 100
  ..height = 50
  ..onPressed = () => print('clicked');

// 2. 集合转换和过滤
final numbers = [1, 2, 3, 4, 5];
// 链式操作
final result = numbers
    .where((n) => n.isEven)        // 过滤偶数
    .map((n) => n * 2)             // 每个数乘2
    .fold(0, (sum, n) => sum + n); // 求和

// 3. 集合展开操作符
final list1 = [1, 2, 3];
final list2 = [4, 5, 6];
final combined = [...list1, ...list2]; // [1, 2, 3, 4, 5, 6]

3. 异步操作技巧

dart 复制代码
// 1. 并发请求处理
Future<void> fetchMultipleData() async {
  final results = await Future.wait([
    fetchUser(),
    fetchOrders(),
    fetchProducts(),
  ]);

  final user = results[0];
  final orders = results[1];
  final products = results[2];
}

// 2. 超时处理
Future<String> fetchWithTimeout() async {
  try {
    return await fetchData().timeout(
      Duration(seconds: 5),
      onTimeout: () => throw TimeoutException('请求超时'),
    );
  } on TimeoutException {
    return '默认数据';
  }
}

// 3. 重试机制
Future<T> retry<T>(
  Future<T> Function() fn, {
  int maxAttempts = 3,
  Duration delay = const Duration(seconds: 1),
}) async {
  try {
    return await fn();
  } catch (e) {
    if (maxAttempts > 1) {
      await Future.delayed(delay);
      return retry(fn, maxAttempts: maxAttempts - 1, delay: delay);
    }
    rethrow;
  }
}

常见陷阱和解决方案

1. 空安全相关陷阱

dart 复制代码
// 1. late 变量初始化陷阱
class User {
  // ❌ 危险:可能导致运行时错误
  late String name;

  // ✅ 安全:提供默认值或在构造函数中初始化
  late final String name;
  User(this.name);
}

// 2. 强制非空断言陷阱
// ❌ 危险:可能抛出异常
void processName(String? name) {
  print(name!.toUpperCase());
}

// ✅ 安全:使用空值检查
void processName(String? name) {
  if (name != null) {
    print(name.toUpperCase());
  }
}

// 3. 集合空安全处理
// ❌ 不安全
List<String>? names;
final firstItem = names![0];

// ✅ 安全
List<String>? names;
final firstItem = names?.firstOrNull ?? 'default';

2. 异步编程陷阱

dart 复制代码
// 1. Future 的错误处理
// ❌ 错误:遗漏错误处理
void fetchData() async {
  final data = await api.getData();
  processData(data);
}

// ✅ 正确:添加错误处理
void fetchData() async {
  try {
    final data = await api.getData();
    processData(data);
  } catch (e) {
    print('获取数据失败: $e');
    // 错误恢复逻辑
  }
}

// 2. Stream 订阅管理
class DataService {
  StreamSubscription? _subscription;

  // ❌ 错误:没有取消订阅
  void startListening() {
    _subscription = stream.listen((_) {});
  }

  // ✅ 正确:在适当时机取消订阅
  void dispose() {
    _subscription?.cancel();
    _subscription = null;
  }
}

3. 性能相关陷阱

dart 复制代码
// 1. 列表操作优化
// ❌ 性能不佳
void processItems(List<String> items) {
  for (var i = 0; i < items.length; i++) {
    print(items[i]);
  }
}

// ✅ 性能更好
void processItems(List<String> items) {
  for (final item in items) {
    print(item);
  }
}

// 2. 内存泄漏防范
class Controller {
  Timer? _timer;

  // ❌ 可能导致内存泄漏
  void startTimer() {
    _timer = Timer.periodic(Duration(seconds: 1), (_) {
      // 处理逻辑
    });
  }

  // ✅ 正确处理资源释放
  void dispose() {
    _timer?.cancel();
    _timer = null;
  }
}

4. 状态管理陷阱

dart 复制代码
// 1. 状态更新
// ❌ 不推荐:直接修改状态
class Counter {
  int count = 0;
  void increment() => count++;
}

// ✅ 推荐:使用不可变状态
class Counter {
  final int count;
  Counter(this.count);

  Counter increment() => Counter(count + 1);
}

// 2. 对象比较
// ❌ 可能导致不必要的重建
class User {
  final String name;
  User(this.name);
}

// ✅ 实现相等性比较
class User {
  final String name;
  User(this.name);

  @override
  bool operator ==(Object other) =>
    identical(this, other) ||
    other is User &&
    runtimeType == other.runtimeType &&
    name == other.name;

  @override
  int get hashCode => name.hashCode;
}

希望这篇文章对您的 Flutter 开发之旅有所帮助。如果觉得有用,请点赞转发,您的支持是我持续创作的动力!

参考资源

相关推荐
lichong9517 小时前
【Flutter&Dart】 拖动边界线改变列宽并且有边界高亮和鼠标效果(12 /100)
android·flutter·计算机外设·api·postman·smartapi·postapi
lichong9518 小时前
【Flutter&Dart】 拖动边界线改变列宽类似 vscode 那种拖动改变编辑框窗口大小(11 /100)
android·ide·vscode·flutter·api·postman·smartapi
low神10 小时前
Flutter面试题、Dart面试题
前端·javascript·flutter·react native·dart·前端面试题
LuiChun14 小时前
创建flutter项目遇到无法连接源的问题
flutter
lichong95115 小时前
【Flutter&Dart】页面切换 PageView &PageController(9 /100)
android·flutter·ios·api·postman·postapi·foxapi
星释15 小时前
鸿蒙Flutter实战:15-Flutter引擎Impeller鸿蒙化、性能优化与未来
flutter·harmonyos·鸿蒙
桂月二二1 天前
解锁2025编程新高度:深入探索编程技术的最新趋势
前端·人工智能·flutter·neo4j·wasm
lichong9511 天前
【Flutter&Dart】 拖动改变 widget 的窗口尺寸大小GestureDetector~简单实现(10 /100)
android·flutter·api·postman·smartapi·postapi·foxapi
low神1 天前
Flutter路由钩子
前端·javascript·flutter·前端面试题
sunly_1 天前
Flutter:打包apk,安卓版本更新(二)
android·flutter