Flutter 鸿蒙开发实践:利用三方库集成实现跨端排序算法可视化实验室

欢迎加入开源鸿蒙跨平台社区: https://openharmonycrossplatform.csdn.net

1. 前言

对于进阶阶段的鸿蒙(HarmonyOS)开发者来说,UI 不仅仅是按钮的堆砌,更是数据的表现。算法可视化是理解抽象排序逻辑的最佳方式之一,而跨端框架能让这份实现同时落地鸿蒙与多端场景。本文将带你通过 Flutter 构建一个排序算法可视化工具,学习如何利用三方库 `provider` 管理复杂的数组状态,并在鸿蒙虚拟机上实时演示冒泡排序(Bubble Sort)的动态过程。最终实现的工具可直接运行在 HarmonyOS Next 虚拟机,也能无缝适配 Android/iOS 等平台。

2. 核心关键词

  • Flutter: 跨端 UI 开发框架,一套代码适配鸿蒙/Android/iOS 等终端。

  • 三方库:

    • `provider`: 轻量级状态管理库,实现数组状态与 UI 组件的响应式绑定;

    • `async`: 异步控制增强,实现排序过程的逐帧延迟可视化。

  • 鸿蒙: HarmonyOS Next 运行环境(虚拟机完美适配,支持 Flutter 应用的全量功能)。

  • 排序可视化: 通过柱状图高度映射数组值,以颜色/位置变化呈现排序过程。

3. 项目案例:Harmony AlgoVisual

3.1 功能设计

创建一个包含多个彩色柱状条的画布,每个柱子的高度代表一个随机生成的数值;点击“开始排序”按钮后,柱状条会以冒泡排序的逻辑逐次交换位置,并用不同颜色标记“正在比较”“已交换”“已排序”的元素;排序完成后可一键重置数组,重新演示。

3.2 界面结构

  • 顶部操作栏:“生成随机数组”“开始排序”“重置”按钮;

  • 中间可视化区域:柱状条画布,占屏幕主要区域;

  • 底部信息栏:显示当前排序步骤、已交换次数等统计信息。

4. 第一步:配置依赖

在 `pubspec.yaml` 中引入状态管理库和异步工具库,这能帮助我们在算法运行过程中精准触发 UI 的局部刷新,同时控制排序动画的节奏:

name: harmony_algovisual
description: A Flutter-based sorting algorithm visualization tool for HarmonyOS
version: 1.0.0+1

environment:
  sdk: '>=3.0.0 <4.0.0'
  flutter: '>=3.10.0'

dependencies:
  flutter:
    sdk: flutter
  # 三方库:用于高效管理排序数组的状态同步
  provider: ^6.1.1
  # 三方库:增强异步流程控制,实现排序动画延迟
  async: ^2.11.0
  # 基础UI组件增强
  material_design_icons_flutter: ^7.0.7299

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^2.0.0

flutter:
  uses-material-design: true
  # 适配鸿蒙虚拟机屏幕尺寸
  generate: true

执行 `flutter pub get` 安装依赖,确保鸿蒙开发环境已配置 Flutter 插件(DevEco Studio 需安装 Flutter 插件并关联 SDK)。

5. 第二步:状态管理设计(Provider)

5.1 定义排序状态模型

创建 `lib/models/sort_state.dart`,封装数组、排序状态、颜色标记等核心数据:

import 'package:flutter/foundation.dart';
import 'package:async/async.dart';

// 排序元素状态枚举
enum ElementStatus {
  normal,    // 未处理
  comparing, // 正在比较
  swapped,   // 已交换
  sorted     // 已排序
}

// 单个柱状条数据模型
class BarModel {
  final int value;
  ElementStatus status;

  BarModel({
    required this.value,
    this.status = ElementStatus.normal,
  });
}

// 排序状态管理类(继承ChangeNotifier实现响应式)
class SortState extends ChangeNotifier {
  List<BarModel> _bars = [];
  bool _isSorting = false;
  int _swapCount = 0;
  int _stepCount = 0;
  // 异步任务取消器,用于终止未完成的排序
  CancelableOperation? _sortOperation;

  List<BarModel> get bars => _bars;
  bool get isSorting => _isSorting;
  int get swapCount => _swapCount;
  int get stepCount => _stepCount;

  // 生成随机数组
  void generateRandomBars({int count = 20, int maxValue = 300}) {
    if (_isSorting) return;
    _bars = List.generate(count, (index) {
      return BarModel(
        value: Random().nextInt(maxValue) + 50, // 避免数值过小
      );
    });
    _resetStats();
    notifyListeners();
  }

  // 重置排序状态
  void resetSort() {
    _sortOperation?.cancel();
    _isSorting = false;
    _resetStats();
    for (var bar in _bars) {
      bar.status = ElementStatus.normal;
    }
    notifyListeners();
  }

  // 重置统计数据
  void _resetStats() {
    _swapCount = 0;
    _stepCount = 0;
  }

  // 冒泡排序核心逻辑(带可视化延迟)
  Future<void> startBubbleSort() async {
    if (_isSorting || _bars.isEmpty) return;
    _isSorting = true;
    _resetStats();
    notifyListeners();

    // 使用CancelableOperation支持排序中断
    _sortOperation = CancelableOperation.fromFuture(
      _bubbleSortImpl(),
      onCancel: () => _isSorting = false,
    );

    await _sortOperation?.value;
    _isSorting = false;
    // 标记所有元素为已排序
    for (var bar in _bars) {
      bar.status = ElementStatus.sorted;
    }
    notifyListeners();
  }

  // 冒泡排序实现(带可视化)
  Future<void> _bubbleSortImpl() async {
    final list = List.of(_bars);
    final length = list.length;

    for (int i = 0; i < length - 1; i++) {
      for (int j = 0; j < length - i - 1; j++) {
        if (!_isSorting) return; // 检测取消信号

        // 标记正在比较的元素
        list[j].status = ElementStatus.comparing;
        list[j + 1].status = ElementStatus.comparing;
        _stepCount++;
        notifyListeners();
        await Future.delayed(const Duration(milliseconds: 200)); // 可视化延迟

        // 交换逻辑
        if (list[j].value > list[j + 1].value) {
          // 交换元素
          final temp = list[j];
          list[j] = list[j + 1];
          list[j + 1] = temp;
          // 标记已交换
          list[j].status = ElementStatus.swapped;
          list[j + 1].status = ElementStatus.swapped;
          _swapCount++;
          notifyListeners();
          await Future.delayed(const Duration(milliseconds: 300));
        }

        // 恢复状态(除了已排序的末尾元素)
        if (j + 1 != length - i - 1) {
          list[j].status = ElementStatus.normal;
          list[j + 1].status = ElementStatus.normal;
        } else {
          list[j + 1].status = ElementStatus.sorted; // 标记已排序的元素
        }
        notifyListeners();
        await Future.delayed(const Duration(milliseconds: 100));
      }
    }

    // 标记第一个元素为已排序
    list[0].status = ElementStatus.sorted;
    _bars = list;
  }
}

5.2 提供状态到全局上下文

在 `lib/main.dart` 中通过 `ChangeNotifierProvider` 注入状态:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:harmony_algovisual/models/sort_state.dart';
import 'package:harmony_algovisual/ui/sort_visual_screen.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => SortState()..generateRandomBars(), // 初始化生成数组
      child: MaterialApp(
        title: 'Harmony AlgoVisual',
        theme: ThemeData(
          primarySwatch: Colors.blue,
          // 适配鸿蒙系统的Material样式
          platform: TargetPlatform.android, 
        ),
        home: const SortVisualScreen(),
        debugShowCheckedModeBanner: false,
      ),
    );
  }
}

6. 第三步:可视化界面实现

创建 `lib/ui/sort_visual_screen.dart`,实现柱状条绘制和交互逻辑:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:harmony_algovisual/models/sort_state.dart';

class SortVisualScreen extends StatelessWidget {
  const SortVisualScreen({super.key});

  // 绘制单个柱状条
  Widget _buildBar(BuildContext context, BarModel bar, double width) {
    Color barColor;
    switch (bar.status) {
      case ElementStatus.comparing:
        barColor = Colors.orange;
        break;
      case ElementStatus.swapped:
        barColor = Colors.red;
        break;
      case ElementStatus.sorted:
        barColor = Colors.green;
        break;
      default:
        barColor = Colors.blueAccent;
    }

    return Container(
      width: width,
      margin: const EdgeInsets.symmetric(horizontal: 1),
      decoration: BoxDecoration(
        color: barColor,
        borderRadius: const BorderRadius.vertical(top: Radius.circular(4)),
      ),
      child: Align(
        alignment: Alignment.bottomCenter,
        child: Container(
          height: bar.value.toDouble(),
        ),
      ),
    );
  }

  
  Widget build(BuildContext context) {
    final sortState = Provider.of<SortState>(context);
    final screenWidth = MediaQuery.of(context).size.width;
    final barWidth = (screenWidth - 40) / sortState.bars.length; // 计算柱状条宽度

    return Scaffold(
      appBar: AppBar(
        title: const Text('Harmony 排序可视化实验室'),
        centerTitle: true,
        // 适配鸿蒙系统状态栏
        systemOverlayStyle: SystemUiOverlayStyle.light,
      ),
      body: Column(
        children: [
          // 操作栏
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: [
                ElevatedButton(
                  onPressed: sortState.isSorting 
                      ? null 
                      : () => sortState.generateRandomBars(),
                  child: const Text('生成随机数组'),
                ),
                ElevatedButton(
                  style: ElevatedButton.styleFrom(
                    backgroundColor: Colors.green,
                  ),
                  onPressed: sortState.isSorting 
                      ? null 
                      : () => sortState.startBubbleSort(),
                  child: const Text('开始排序'),
                ),
                ElevatedButton(
                  style: ElevatedButton.styleFrom(
                    backgroundColor: Colors.grey,
                  ),
                  onPressed: () => sortState.resetSort(),
                  child: const Text('重置'),
                ),
              ],
            ),
          ),
          // 可视化区域
          Expanded(
            child: Padding(
              padding: const EdgeInsets.symmetric(horizontal: 20),
              child: Align(
                alignment: Alignment.bottomCenter,
                child: Row(
                  crossAxisAlignment: CrossAxisAlignment.end,
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: sortState.bars
                      .map((bar) => _buildBar(context, bar, barWidth))
                      .toList(),
                ),
              ),
            ),
          ),
          // 统计信息栏
          Container(
            padding: const EdgeInsets.all(10),
            color: Colors.grey[100],
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Text('排序步骤:${sortState.stepCount}'),
                Text('交换次数:${sortState.swapCount}'),
                Text('状态:${sortState.isSorting ? '排序中' : '就绪'}'),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

7. 第四步:鸿蒙环境适配与运行

7.1 鸿蒙虚拟机配置

  1. 确保 DevEco Studio 已安装 Flutter 插件(Settings → Plugins → Flutter);

  2. 配置 Flutter SDK 路径(Settings → Languages &amp; Frameworks → Flutter);

  3. 创建 HarmonyOS Next 虚拟机(API 9+),确保虚拟机已启动。

7.2 运行应用

  1. 在终端执行 `flutter clean` 清理缓存;

  2. 执行 `flutter pub get` 确保依赖完整;

  3. 执行 `flutter run` 选择鸿蒙虚拟机作为运行目标;

  4. 等待应用编译并安装到鸿蒙虚拟机,即可看到可视化界面。

7.3 适配注意事项

  • 鸿蒙系统对 Flutter 插件的兼容性:确保使用的三方库版本不依赖鸿蒙不支持的原生 API;

  • 屏幕尺寸适配:通过 `MediaQuery` 获取鸿蒙虚拟机屏幕尺寸,动态计算柱状条宽度;

  • 性能优化:排序数组长度建议控制在 20-30 之间,避免鸿蒙虚拟机性能瓶颈。

8. 扩展功能与优化

8.1 支持更多排序算法

基于现有状态模型,可快速扩展插入排序、选择排序、快速排序等算法,只需新增 `startInsertionSort()`、`startQuickSort()` 等方法。

8.2 自定义排序参数

添加滑块组件,允许用户调整:

  • 数组长度(10-50);

  • 排序动画速度(100ms-1000ms);

  • 柱状条颜色主题。

8.3 鸿蒙特有功能适配

  • 集成鸿蒙系统的“悬浮窗”能力,让排序可视化在后台运行;

  • 适配鸿蒙的深色模式,实现主题切换;

  • 接入鸿蒙系统的性能分析工具,优化动画帧率。

9. 总结

本文通过 Flutter + Provider 实现了排序算法可视化工具,并适配鸿蒙(HarmonyOS)运行环境。核心要点包括:

  1. 利用 Provider 实现数组状态的响应式管理,精准触发 UI 刷新;

  2. 通过异步延迟控制排序动画节奏,提升可视化效果;

  3. 适配鸿蒙虚拟机的运行环境,实现跨端体验;

  4. 封装清晰的状态模型和 UI 组件,便于扩展更多算法。

该实践不仅帮助开发者理解排序算法的核心逻辑,也掌握了 Flutter 状态管理、异步控制、鸿蒙适配的关键技巧,为鸿蒙跨端应用开发提供了可复用的思路。

运行截图:
在这里插入图片描述

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐