欢迎加入开源鸿蒙PC社区: https://harmonypc.csdn.net/
欢迎在PC社区平台申请新建项目:https://atomgit.com/OpenHarmonyPCDeveloper
AtomGit 仓库地址:https://atomgit.com/OpenHarmonyPCDeveloper/ohos_rust_cargo

本文讲解鸿蒙 PC 端 Rust 开发环境搭建,鸿蒙基于 musl 库、强制二进制签名,无法直接使用通用 Linux 编译产物。需借助鸿蒙专属包管理器 Harmonybrew,提供两套编译方案:方案一安装 llvm-gcc-compat,零配置开箱即用;方案二仅安装 ohos-sdk,需手动配置 Cargo 链接器,二者都依托 ohos-sdk 完成自动签名编译。

完整的过程可以参考一下:

【OpenHarmony 鸿蒙 PC + CodeArts IDE 实现 Rust开发完整开发环境搭建指南】


一、indicatif 库介绍

indicatif 是 Rust 最流行的终端进度条、加载动画库,专门美化命令行输出,解决脚本/批量任务看不到执行进度的问题。

核心能力

  1. 基础进度条:显示当前/总量、百分比、速度、剩余时间
  2. 旋转加载动画(spinner):无固定总量的等待场景(文件下载、接口请求)
  3. 多进度条并行(同时多个任务进度)
  4. 自定义样式、彩色文字、自定义模板
  5. 支持长文本、换行日志不打乱进度条

适用场景

批量文件处理、数据库批量导入、文件下载、爬虫、打包编译、任何长时间运行的 CLI 工具。

二、安装命令

cargo add indicatif

自动写入 Cargo.toml:

[dependencies]
indicatif = "0.17"

请添加图片描述

三、完整无报错示例代码 main.rs

覆盖三大常用场景:旋转加载动画、单进度条、多并行进度条

use indicatif::{ProgressBar, ProgressStyle, MultiProgress};
use std::thread;
use std::time::Duration;

fn main() {
    println!("===== 1. 旋转等待动画(无总量,等待场景) =====");
    spinner_demo();

    println!("\n===== 2. 标准带总量进度条 =====");
    progress_bar_demo();

    println!("\n===== 3. 多任务并行进度条 =====");
    multi_progress_demo();
}

/// 旋转加载动画:不知道总数量时使用
fn spinner_demo() {
    let sp = ProgressBar::new_spinner();
    // template 返回 Result,必须 unwrap()
    let style = ProgressStyle::default_spinner()
        .tick_chars("⠁⠂⠄⡀⢀⠠⠐⠈ ")
        .template("{spinner:.blue} {msg}")
        .unwrap();
    sp.set_style(style);
    sp.set_message("正在请求接口,请稍候...");

    // 持续刷新动画
    for _ in 0..30 {
        sp.tick();
        thread::sleep(Duration::from_millis(80));
    }
    sp.finish_with_message("✅ 接口请求完成");
}

/// 普通进度条:已知任务总量
fn progress_bar_demo() {
    let total = 100;
    let pb = ProgressBar::new(total);

    // 进度模板解包
    let style = ProgressStyle::default_bar()
        .template(
            "{msg}\n[{elapsed_precise}] [{bar:40.cyan/blue}] {pos}/{len} ({percent}%) 剩余:{eta}",
        )
        .unwrap()
        .progress_chars("#>-");

    pb.set_style(style);
    pb.set_message("批量处理文件中");

    for i in 0..total {
        pb.set_position(i as u64);
        thread::sleep(Duration::from_millis(30));
    }
    pb.finish_with_message("✅ 全部文件处理完毕");
}

/// 多任务并行进度条(同时显示多个进度)
fn multi_progress_demo() {
    let multi = MultiProgress::new();

    // 任务1 样式
    let style1 = ProgressStyle::default_bar()
        .template("[{bar:30.green}] {pos}/{len} {msg}")
        .unwrap();
    let pb1 = multi.add(ProgressBar::new(50));
    pb1.set_message("任务一:图片压缩");
    pb1.set_style(style1);

    // 任务2 样式
    let style2 = ProgressStyle::default_bar()
        .template("[{bar:30.yellow}] {pos}/{len} {msg}")
        .unwrap();
    let pb2 = multi.add(ProgressBar::new(80));
    pb2.set_message("任务二:数据入库");
    pb2.set_style(style2);

    // 两个线程模拟并行执行
    let h1 = thread::spawn(move || {
        for i in 0..50 {
            pb1.set_position(i);
            thread::sleep(Duration::from_millis(50));
        }
        pb1.finish_with_message("任务一完成");
    });

    let h2 = thread::spawn(move || {
        for i in 0..80 {
            pb2.set_position(i);
            thread::sleep(Duration::from_millis(35));
        }
        pb2.finish_with_message("任务二完成");
    });

    // 等待线程结束
    h1.join().unwrap();
    h2.join().unwrap();
}

请添加图片描述


一、库基础前置说明

indicatif 是 Rust 命令行进度美化库,用于 CLI 工具展示加载旋转动画、单进度条、多并行进度条,解决长时间任务看不到执行状态的问题。
当前代码适配 indicatif 0.18+.template() 返回 Result,必须调用 .unwrap() 解包,这是新版和旧版最大区别。

二、顶部导入解析

use indicatif::{ProgressBar, ProgressStyle, MultiProgress};
use std::thread;
use std::time::Duration;
  1. ProgressBar:核心进度对象,包含旋转加载器、固定总量进度条两种形态
  2. ProgressStyle:进度条样式构造器,自定义模板、颜色、填充字符、旋转图标
  3. MultiProgress:多进度条容器,支持终端同时展示多条独立进度(多线程并行任务)
  4. std::thread:多线程模拟并行任务
  5. std::time::Duration:线程休眠,模拟任务耗时

三、入口 main 函数

fn main() {
    println!("===== 1. 旋转等待动画(无总量,等待场景) =====");
    spinner_demo();

    println!("\n===== 2. 标准带总量进度条 =====");
    progress_bar_demo();

    println!("\n===== 3. 多任务并行进度条 =====");
    multi_progress_demo();
}

按顺序执行三类最常用进度组件,分开演示方便观察每种效果:

  1. 无总量旋转加载(不知道任务总数,如网络请求、文件读取)
  2. 已知总量进度条(批量文件、导入数据、下载文件)
  3. 多任务并行多条进度(同时跑多个独立任务)

四、函数1:spinner_demo 旋转加载动画

fn spinner_demo() {
    let sp = ProgressBar::new_spinner();
    // template 返回 Result,必须 unwrap()
    let style = ProgressStyle::default_spinner()
        .tick_chars("⠁⠂⠄⡀⢀⠠⠐⠈ ")
        .template("{spinner:.blue} {msg}")
        .unwrap();
    sp.set_style(style);
    sp.set_message("正在请求接口,请稍候...");

    // 持续刷新动画
    for _ in 0..30 {
        sp.tick();
        thread::sleep(Duration::from_millis(80));
    }
    sp.finish_with_message("✅ 接口请求完成");
}

分步拆解

  1. ProgressBar::new_spinner()
    创建无总量旋转加载器,适用于无法预知任务总数的等待场景:接口请求、读取大文件、等待第三方服务。
  2. ProgressStyle::default_spinner()
    加载旋转动画默认样式基底
    • .tick_chars("⠁⠂⠄⡀⢀⠠⠐⠈ "):自定义旋转图标字符,循环切换形成转动效果
    • .template("{spinner:.blue} {msg}"):定义输出模板
      • {spinner:.blue}:旋转图标,蓝色字体
      • {msg}:自定义提示文本占位
    • .unwrap():新版 template 返回 Result,解析模板无错误才取出样式对象,否则直接崩溃提示模板语法错误
  3. sp.set_style(style):将自定义样式绑定到加载器
  4. sp.set_message("xxx"):填充模板里 {msg} 的文字
  5. 循环 sp.tick():刷新旋转图标,配合休眠制造动画效果
  6. sp.finish_with_message("✅ 接口请求完成"):任务结束,替换旋转动画为完成提示文字

适用场景

网络请求、数据库连接、未知大小文件读取、后台异步等待操作


五、函数2:progress_bar_demo 固定总量进度条

fn progress_bar_demo() {
    let total = 100;
    let pb = ProgressBar::new(total);

    // 进度模板解包
    let style = ProgressStyle::default_bar()
        .template(
            "{msg}\n[{elapsed_precise}] [{bar:40.cyan/blue}] {pos}/{len} ({percent}%) 剩余:{eta}",
        )
        .unwrap()
        .progress_chars("#>-");

    pb.set_style(style);
    pb.set_message("批量处理文件中");

    for i in 0..total {
        pb.set_position(i as u64);
        thread::sleep(Duration::from_millis(30));
    }
    pb.finish_with_message("✅ 全部文件处理完毕");
}

分步拆解

  1. ProgressBar::new(total)
    创建带固定总量的进度条,参数 total 为 u64 类型总任务数(此处100)
  2. ProgressStyle::default_bar() 标准进度条样式基底
    模板占位符解释:
    | 占位符 | 作用 |
    |--------|------|
    | {msg} | 顶部自定义提示文字 |
    | {elapsed_precise} | 已运行精确时间 |
    | {bar:40.cyan/blue} | 进度条宽40字符,已完成青色、未完成蓝色 |
    | {pos}/{len} | 当前进度 / 总任务 |
    | {percent} | 完成百分比 |
    | {eta} | 预估剩余时间 |
  • .progress_chars("#>-"):自定义进度条填充、分隔、空白字符
  • .unwrap() 解析模板
  1. pb.set_position(i as u64):更新当前进度数值,自动刷新百分比、剩余时间
  2. 循环休眠模拟每个任务耗时
  3. finish_with_message:全部任务完成,输出完成标识

适用场景

批量文件转换、数据批量入库、文件下载、爬虫固定条数抓取


六、函数3:multi_progress_demo 多并行进度条

fn multi_progress_demo() {
    let multi = MultiProgress::new();

    // 任务1 样式
    let style1 = ProgressStyle::default_bar()
        .template("[{bar:30.green}] {pos}/{len} {msg}")
        .unwrap();
    let pb1 = multi.add(ProgressBar::new(50));
    pb1.set_message("任务一:图片压缩");
    pb1.set_style(style1);

    // 任务2 样式
    let style2 = ProgressStyle::default_bar()
        .template("[{bar:30.yellow}] {pos}/{len} {msg}")
        .unwrap();
    let pb2 = multi.add(ProgressBar::new(80));
    pb2.set_message("任务二:数据入库");
    pb2.set_style(style2);

    // 两个线程模拟并行执行
    let h1 = thread::spawn(move || {
        for i in 0..50 {
            pb1.set_position(i);
            thread::sleep(Duration::from_millis(50));
        }
        pb1.finish_with_message("任务一完成");
    });

    let h2 = thread::spawn(move || {
        for i in 0..80 {
            pb2.set_position(i);
            thread::sleep(Duration::from_millis(35));
        }
        pb2.finish_with_message("任务二完成");
    });

    // 等待线程结束
    h1.join().unwrap();
    h2.join().unwrap();
}

分步拆解

  1. MultiProgress::new()
    多进度条管理器,解决多条进度条输出互相覆盖、排版混乱问题,自动分行管理多个 ProgressBar
  2. multi.add(ProgressBar)
    把单个进度条加入管理器,所有进度条共用终端输出流,互不干扰
  3. 分别构建两个独立进度条,设置不同颜色(绿色/黄色)、不同总任务量、不同提示文字
  4. thread::spawn(move || {})
    创建独立线程分别更新两条进度,模拟并行执行两个业务任务
    • move 闭包捕获进度条所有权移入线程
    • 循环内不断更新进度位置,休眠模拟业务处理耗时
  5. h1.join().unwrap(); h2.join().unwrap();
    主线程阻塞等待两个子线程全部执行完毕,防止程序提前退出进度条消失

适用场景

多文件同时下载、多目录并行处理、多数据源同步导入、多爬虫任务并发执行

七、核心使用总结

  1. 不知道任务总数 → ProgressBar::new_spinner() 旋转加载器
  2. 固定任务总量单任务 → ProgressBar::new(num) 标准进度条
  3. 多并发任务同时展示多条进度 → 搭配 MultiProgress 容器
  4. 0.18+ 版本模板字符串后必须加 .unwrap() 解包 Result
  5. 所有进度更新、完成、提示文字 API 统一,上手成本极低

四、核心API详细解释

1. ProgressBar 两种创建方式

  1. 旋转动画:ProgressBar::new_spinner()
    适合无明确总量:网络请求、等待资源、后台加载

    • .tick():刷新旋转图标
    • .set_message("文字"):左侧提示文字
    • .finish_with_message("完成提示"):结束后替换文字
  2. 固定总量进度条:ProgressBar::new(总数值u64)

    • .set_position(当前数值) 更新进度
    • .inc(1) 自增1(简写写法)
    • .finish() / .finish_with_message() 标记完成

2. ProgressStyle 模板占位符(常用)

占位符 含义
{spinner} 旋转图标
{bar:宽度.前景/背景} 进度条主体
{pos} 当前进度
{len} 总长度
{percent} 百分比
{elapsed_precise} 已运行时间
{eta} 预估剩余时间
{msg} 自定义提示文本

3. MultiProgress 多进度条

  • MultiProgress::new() 创建进度条容器
  • multi.add(pb) 将进度条加入容器,实现多行同时展示
  • 搭配多线程可模拟并行任务进度

五、极简常用片段(直接复制使用)

简易自增进度条

use indicatif::ProgressBar;
use std::time::Duration;

fn simple_bar() {
    let pb = ProgressBar::new(20);
    for _ in 0..20 {
        pb.inc(1);
        std::thread::sleep(Duration::from_millis(100));
    }
    pb.finish();
}

简易加载spinner

use indicatif::ProgressBar;
use std::time::Duration;

fn simple_spin() {
    let sp = ProgressBar::new_spinner();
    sp.set_message("加载中...");
    for _ in 0..20 {
        sp.tick();
        std::thread::sleep(Duration::from_millis(100));
    }
    sp.finish();
}

六、典型业务场景

  1. 爬虫批量请求页面,展示爬取进度
  2. 本地批量转换图片/视频,可视化处理进度
  3. 命令行文件上传/下载进度展示
  4. 大数据批量导入数据库,直观查看剩余任务量
  5. CLI工具长时间任务优化终端交互体验

更多推荐