Flutter 鸿蒙 disk_space_2 1.0.13 使用实战:下载前检查磁盘空间
本文用
disk_space_2 1.0.13在 Flutter
鸿蒙应用中读取总容量、可用容量和指定目录的可用容量,并把查询结果用于下载前空间检查。示例依赖锁定到真机受测提交,返回单位、异常处理和路径边界都按实际
API 说明。三方库仓库: https://atomgit.com/oh-flutter/disk_space_2
本文锁定版本:
0cb25f91bdda96fddbdfd465ea189678e2cf959b完整 Demo: disk_space_2/example(受测提交)
一、最终真机效果

图 1:CHZ-AL00 / HarmonyOS 7.0.0.105 上读取总量、空闲量和应用沙箱目录空闲量。


本次样本中,总容量为 103460 MiB,可用容量为 67477.16015625 MiB。默认目录和测试用沙箱目录位于同一文件系统,因此两次可用容量相同;这不是硬编码值,设备写入数据后会变化。
| 使用场景 | 真机结果 |
|---|---|
| 查询总容量 | 成功,返回 double,单位 MiB |
| 查询默认可用容量 | 成功 |
| 查询应用沙箱目录 | 成功 |
| 查询不存在目录 | 明确失败,没有回退到默认目录 |
| 自动化与构建 | 13 项 Dart/Widget 测试、静态分析和 HAP 构建通过 |
二、接入前先确认三个语义
第一,三个容量接口返回的都是 MiB,即 1 MiB = 1024 * 1024 bytes,不是 bytes,也不是以 1000 为进位的 MB。若页面要显示 GiB,应在展示层继续除以 1024。
第二,查询结果描述的是目标路径所在文件系统。它适合回答“这个应用目录还能不能放下一个文件”,不等于设备所有物理介质的总和,也不能作为固定硬件规格保存。
第三,指定路径必须是应用能够访问的真实本地目录。不要传文档 URI、普通文件、其他应用私有目录或不存在的路径。错误不能按 0 处理,因为 0 也可能表示文件系统确实已经没有可用空间。
三、环境与依赖
| 组件 | 实测版本 |
|---|---|
| Flutter OH | 3.41.10-ohos-1.0.1 |
| Dart | 3.11.5 |
| DevEco Studio | 26.0.0 Release |
| HarmonyOS SDK | API 26,示例兼容 API 18 |
| 测试设备 | CHZ-AL00 / HarmonyOS 7.0.0.105 |
| disk_space_2 | 1.0.13 / 上述受测提交 |
版本号更大的 3.44.9+ohos-0.0.1-canary1 是预览版,不是本文的实测环境。当前 OHOS 适配尚未发布稳定 TAG,因此业务工程应锁定完整 SHA:
dependencies:
disk_space_2:
git:
url: https://atomgit.com/oh-flutter/disk_space_2.git
ref: 0cb25f91bdda96fddbdfd465ea189678e2cf959b
flutter pub get
flutter pub deps
随后在 pubspec.lock 中确认 resolved-ref 与受测 SHA 一致。容量查询不需要新增鸿蒙权限;示例中的调试网络权限也不是该库的功能要求。

图 2:AtomGit 仓库、OHOS 适配分支和当前提交核对。
四、核心 API 用法
import 'dart:io';
import 'package:disk_space_2/disk_space_2.dart';
Future<Map<String, double?>> loadDiskSpace() async {
final directory = Directory.systemTemp;
if (!directory.existsSync()) {
throw StateError('应用临时目录不存在');
}
return <String, double?>{
'totalMiB': await DiskSpace.getTotalDiskSpace,
'freeMiB': await DiskSpace.getFreeDiskSpace,
'directoryFreeMiB':
await DiskSpace.getFreeDiskSpaceForPath(directory.path),
};
}
getTotalDiskSpace 和 getFreeDiskSpace 是静态异步 getter;指定目录使用 getFreeDiskSpaceForPath(path)。返回类型可空,所以业务既要处理平台异常,也要处理 null。如果下载包还需要解压,阈值不要只等于压缩包大小,应叠加解压空间和安全余量。
bool hasEnoughSpace(double? freeMiB, int downloadBytes) {
if (freeMiB == null) return false;
final requiredMiB = downloadBytes / (1024 * 1024);
const reserveMiB = 256.0;
return freeMiB >= requiredMiB + reserveMiB;
}
五、可直接放进页面的查询流程
import 'dart:io';
import 'package:disk_space_2/disk_space_2.dart';
import 'package:flutter/material.dart';
class DiskSpacePage extends StatefulWidget {
const DiskSpacePage({super.key});
State<DiskSpacePage> createState() => _DiskSpacePageState();
}
class _DiskSpacePageState extends State<DiskSpacePage> {
double? _total;
double? _free;
double? _pathFree;
Object? _error;
bool _loading = false;
void initState() {
super.initState();
_refresh();
}
Future<void> _refresh() async {
if (_loading) return;
setState(() {
_loading = true;
_error = null;
});
try {
final values = await Future.wait<double?>([
DiskSpace.getTotalDiskSpace,
DiskSpace.getFreeDiskSpace,
DiskSpace.getFreeDiskSpaceForPath(Directory.systemTemp.path),
]);
if (!mounted) return;
setState(() {
_total = values[0];
_free = values[1];
_pathFree = values[2];
});
} catch (error) {
if (mounted) setState(() => _error = error);
} finally {
if (mounted) setState(() => _loading = false);
}
}
String _format(double? value) =>
value == null ? '不可用' : '${(value / 1024).toStringAsFixed(2)} GiB';
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: const Text('存储空间'),
actions: [
IconButton(
tooltip: '刷新',
onPressed: _loading ? null : _refresh,
icon: const Icon(Icons.refresh),
),
],
),
body: ListView(
padding: const EdgeInsets.all(16),
children: [
ListTile(title: const Text('总容量'), subtitle: Text(_format(_total))),
ListTile(title: const Text('可用容量'), subtitle: Text(_format(_free))),
ListTile(
title: const Text('临时目录可用容量'),
subtitle: Text(_format(_pathFree)),
),
if (_loading) const LinearProgressIndicator(),
if (_error != null) Text('查询失败:$_error'),
],
),
);
}
页面在 Future 完成后检查 mounted,并在请求期间禁用刷新,避免旧结果覆盖新状态。真实下载任务还应在开始写文件前再查一次,因为用户可能在页面展示后继续占用空间。

图 3:OHOS 端使用应用目录、statvfs 查询和 MiB 换算。
六、测试、构建与真机核对
flutter analyze
flutter test
cd example
flutter test
flutter build hap --debug --no-codesign

图 4:13 项 Dart/Widget 测试和静态检查结果。

图 5:HAP 构建信息及真机宿主锁定的远程提交。

图 6:容量读取、沙箱目录成功和不存在目录失败的真实记录。
真机数据只代表测试时刻。自动化、HAP 构建和安装也不能代替容量 API 的实际调用,因此发布时应同时保留图 1 和图 6。
七、常见问题
Q1:为什么拿到的是几万而不是几百 GB
返回单位是 MiB。显示 GiB 时除以 1024,不要再次按 bytes 除以 1024 * 1024 * 1024。
Q2:目录查询为什么抛异常
确认路径存在、是目录、属于应用可访问范围且不是 URI。失败时提示用户清理空间或重试,不要改查默认目录后假装目标目录可写。
Q3:free 与下一秒读取的结果不同正常吗
正常。系统缓存、日志和其他进程都可能改变可用容量。业务测试应比较范围和阈值,不应断言一个固定小数。
八、总结
disk_space_2 适合在下载、解压和缓存前查询目标文件系统。可靠接入的关键是锁定受测 SHA、牢记返回单位为 MiB、只查询应用可访问目录,并把空值和异常与“空间为 0”分开处理。本文已在 API 26 真机验证三个查询及非法路径边界。
九、参考链接
欢迎加入CPF-Flutter 鸿蒙社区:https://atomgit.com/CPF-Flutter
更多推荐


所有评论(0)