1.4 控制流语句

基础知识

控制流语句用于控制程序执行的顺序,允许程序根据条件选择不同的执行路径,或者重复执行某些代码块。Dart 提供了多种控制流语句,包括条件语句(if-elseswitch-case)和循环语句(forwhiledo-while)。

1. 条件语句

  • ifelse

    if 语句用于根据条件执行代码块。如果条件为 true,则执行 if 块中的代码;否则,如果存在 else 块,则执行 else 块中的代码。可以使用 else if 来检查多个条件。

    dart
    复制代码
    int score = 85;
    
    if (score >= 90) {
      print("优秀");
    } else if (score >= 60) {
      print("及格");
    } else {
      print("不及格");
    }
  • switchcase

    switch 语句用于根据表达式的值选择多个执行路径中的一个。每个 case 后面跟着一个值,如果表达式的值与 case 的值匹配,则执行该 case 块中的代码。break 语句用于跳出 switch 语句。default 关键字用于处理所有 case 都不匹配的情况。

    dart
    复制代码
    String command = "OPEN";
    
    switch (command) {
      case "OPEN":
        print("打开文件");
        break;
      case "SAVE":
        print("保存文件");
        break;
      case "CLOSE":
        print("关闭文件");
        break;
      default:
        print("未知命令");
    }

2. 循环语句

  • for 循环

    for 循环用于重复执行代码块指定次数。它通常包含初始化、条件和递增/递减表达式。

    dart
    复制代码
    for (int i = 0; i < 5; i++) {
      print("循环次数: $i");
    }
    
    // for-in 循环用于遍历集合
    List<String> fruits = ["apple", "banana", "orange"];
    for (String fruit in fruits) {
      print("水果: $fruit");
    }
  • while 循环

    while 循环在条件为 true 时重复执行代码块。在每次循环迭代之前检查条件。

    dart
    复制代码
    int count = 0;
    while (count < 3) {
      print("计数: $count");
      count++;
    }
  • do-while 循环

    do-while 循环与 while 循环类似,但它至少会执行一次代码块,然后在每次循环迭代之后检查条件。

    dart
    复制代码
    int i = 0;
    do {
      print("执行一次,i = $i");
      i++;
    } while (i < 0); // 条件为 false,但循环体至少执行一次

3. breakcontinue 语句

  • break: 用于立即终止循环或 switch 语句的执行,并跳到循环或 switch 之后的语句。

  • continue: 用于跳过当前循环迭代的剩余部分,并开始下一次迭代。

    dart
    复制代码
    for (int i = 0; i < 10; i++) {
      if (i == 3) {
        continue; // 跳过 3
      }
      if (i == 7) {
        break; // 终止循环
      }
      print(i);
    }
    // 输出: 0, 1, 2, 4, 5, 6

官方文档链接

Flutter 开发中的应用案例

控制流语句在 Flutter 应用中扮演着核心角色,它们用于根据用户交互、数据状态或业务逻辑来动态地构建 UI、处理事件和管理应用流程。

案例:一个动态列表的构建与筛选

我们将创建一个简单的 Flutter 应用,展示一个商品列表,并允许用户根据条件进行筛选。这个案例将演示 if-elsefor-in 循环以及 switch 语句在 Flutter UI 构建中的应用。

dart
复制代码
import 'package:flutter/material.dart';

class Product {
  final String name;
  final double price;
  final String category;

  Product({required this.name, required this.price, required this.category});
}

class ProductListScreen extends StatefulWidget {
  const ProductListScreen({super.key});

  @override
  State<ProductListScreen> createState() => _ProductListScreenState();
}

class _ProductListScreenState extends State<ProductListScreen> {
  List<Product> _allProducts = [
    Product(name: '苹果', price: 5.0, category: '水果'),
    Product(name: '香蕉', price: 3.0, category: '水果'),
    Product(name: '牛奶', price: 12.0, category: '乳制品'),
    Product(name: '面包', price: 8.0, category: '烘焙'),
    Product(name: '酸奶', price: 10.0, category: '乳制品'),
    Product(name: '蛋糕', price: 25.0, category: '烘焙'),
  ];

  String _selectedCategory = '所有';

  List<Product> get _filteredProducts {
    if (_selectedCategory == '所有') {
      return _allProducts;
    } else {
      // 使用 for-in 循环和 if 条件进行筛选
      List<Product> filtered = [];
      for (var product in _allProducts) {
        if (product.category == _selectedCategory) {
          filtered.add(product);
        }
      }
      return filtered;
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('商品列表'),
      ),
      body: Column(
        children: <Widget>[
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: DropdownButton<String>(
              value: _selectedCategory,
              onChanged: (String? newValue) {
                setState(() {
                  _selectedCategory = newValue!;
                });
              },
              items: <String>['所有', '水果', '乳制品', '烘焙']
                  .map<DropdownMenuItem<String>>((String value) {
                return DropdownMenuItem<String>(
                  value: value,
                  child: Text(value),
                );
              }).toList(),
            ),
          ),
          Expanded(
            child: ListView.builder(
              itemCount: _filteredProducts.length,
              itemBuilder: (context, index) {
                final product = _filteredProducts[index];
                return Card(
                  margin: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
                  child: Padding(
                    padding: const EdgeInsets.all(16.0),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: <Widget>[
                        Text(
                          product.name,
                          style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
                        ),
                        const SizedBox(height: 8),
                        Text('价格: ¥${product.price.toStringAsFixed(2)}'),
                        Text('分类: ${product.category}'),
                        // 根据分类使用 switch 语句显示不同图标
                        Builder(
                          builder: (context) {
                            IconData iconData;
                            switch (product.category) {
                              case '水果':
                                iconData = Icons.apple;
                                break;
                              case '乳制品':
                                iconData = Icons.local_drink;
                                break;
                              case '烘焙':
                                iconData = Icons.cake;
                                break;
                              default:
                                iconData = Icons.category;
                            }
                            return Icon(iconData);
                          },
                        ),
                      ],
                    ),
                  ),
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}

void main() {
  runApp(const MaterialApp(home: ProductListScreen()));
}

案例分析:

  • if-else 语句:在 _filteredProducts getter 中,if (_selectedCategory == '所有') 用于判断是否显示所有商品,否则进入 else 块进行筛选。这展示了如何根据条件动态地改变数据源。
  • for-in 循环:在 else 块中,for (var product in _allProducts) 用于遍历所有商品,并结合 if (product.category == _selectedCategory) 条件语句来筛选出符合条件的商品。这在处理列表数据时非常常用。
  • switch 语句:在 itemBuilder 中,我们使用 switch (product.category) 来根据商品的分类显示不同的图标。这是一种清晰地处理多分支条件逻辑的方式。
  • ListView.builder: Flutter 中用于构建长列表的 Widget,它会根据 itemCountitemBuilder 动态地渲染列表项。itemBuilder 内部的逻辑(包括对 product 属性的访问和 switch 语句的使用)直接影响 UI 的呈现。
  • DropdownButton: 这是一个下拉菜单 Widget,onChanged 回调函数中会更新 _selectedCategory 的值,并通过 setState 触发 UI 重建,从而使 _filteredProducts 重新计算并更新列表显示。

这个案例清晰地展示了 Dart 的控制流语句如何在 Flutter 应用中用于实现数据筛选、UI 动态更新和条件渲染。掌握这些语句是构建交互式和响应式 Flutter 应用的关键。