Flutter for OpenHarmony移动数据使用监管助手App实战 - 网速测试实现
网速测试是流量监控App中很受欢迎的功能,用户可以随时检测当前网络的实际速度。这个页面的核心是一个动态的速度仪表盘,配合测试过程的动画效果,给用户直观的反馈。
页面布局设计
网速测试页面采用居中布局,主要元素从上到下依次是:
- 速度仪表盘:环形进度条显示当前测试进度和速度
- 测试结果卡片:延迟、下载速度、上传速度三项数据
- 开始按钮:触发测试的主按钮
速度仪表盘实现
用percent_indicator库的环形进度条作为仪表盘:
Widget _buildSpeedometer() {
return Obx(() => CircularPercentIndicator(
radius: 100.r,
lineWidth: 12.w,
percent: controller.progress.value,
center: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
controller.isTesting.value ? '${controller.downloadSpeed.value.toStringAsFixed(1)}' : '0',
style: TextStyle(fontSize: 36.sp, fontWeight: FontWeight.bold, color: AppTheme.primaryColor),
),
// _buildSpeedometer使用CircularPercentIndicator构建环形仪表盘。
// radius设为100像素,lineWidth设为12像素控制环形粗细。
// percent绑定controller.progress,实现进度动画效果。
Text('Mbps', style: TextStyle(fontSize: 14.sp, color: AppTheme.textSecondary)),
],
),
progressColor: AppTheme.primaryColor,
backgroundColor: Colors.grey.shade200,
circularStrokeCap: CircularStrokeCap.round,
));
}
参数解析:
radius: 100.r:仪表盘半径,100是个比较大的尺寸,作为页面的视觉中心lineWidth: 12.w:进度条粗细,太细看不清,太粗显得笨重percent:进度值,0到1之间,绑定controller的progress变量circularStrokeCap: CircularStrokeCap.round:进度条两端是圆形,比方形更柔和
中心内容:测试中显示实时速度,未测试时显示0。速度数字用36sp的大字号,单位"Mbps"用小字号放在下面。
测试结果卡片
展示延迟、下载、上传三项测试结果:
Widget _buildResults() {
return Container(
margin: EdgeInsets.symmetric(horizontal: 32.w),
padding: EdgeInsets.all(20.w),
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(16.r)),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildResultItem('延迟', '${controller.ping.value}', 'ms'),
_buildResultItem('下载', '${controller.downloadSpeed.value.toStringAsFixed(1)}', 'Mbps'),
_buildResultItem('上传', '${controller.uploadSpeed.value.toStringAsFixed(1)}', 'Mbps'),
// _buildResults构建测试结果卡片,水平外边距32像素。
// 内边距20像素,白色背景配合16像素圆角。
// Row使用spaceAround均匀分布三个结果项。
],
),
);
}
Widget _buildResultItem(String label, String value, String unit) {
return Column(
children: [
Text(label, style: TextStyle(fontSize: 12.sp, color: AppTheme.textSecondary)),
SizedBox(height: 4.h),
Obx(() => Text(value, style: TextStyle(fontSize: 20.sp, fontWeight: FontWeight.bold))),
Text(unit, style: TextStyle(fontSize: 10.sp, color: AppTheme.textSecondary)),
],
);
// _buildResultItem是复用组件,接收标签、数值和单位参数。
// Column垂直排列标签、数值和单位三行文字。
// 数值用Obx包裹实现实时更新,20sp粗体突出显示。
}
三项数据等间距排列,每项包含标签、数值、单位三行。数值用Obx包裹实现实时更新。
开始测试按钮
按钮在测试中和空闲时显示不同的文字:
Widget _buildStartButton() {
return Obx(() => ElevatedButton(
onPressed: controller.isTesting.value ? null : controller.startTest,
style: ElevatedButton.styleFrom(
backgroundColor: AppTheme.primaryColor,
padding: EdgeInsets.symmetric(horizontal: 60.w, vertical: 16.h),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30.r)),
),
child: Text(
controller.isTesting.value ? controller.testPhase.value : '开始测速',
style: TextStyle(fontSize: 16.sp, color: Colors.white),
// _buildStartButton构建开始测试按钮,用Obx包裹响应状态变化。
// 测试中时onPressed设为null禁用按钮,防止重复点击。
// 按钮样式使用主题色背景,30像素圆角形成胶囊形状。
),
));
}
测试中禁用按钮:onPressed设为null会自动禁用按钮,防止用户重复点击。
动态文字:测试中显示当前阶段(“测试延迟…”、"测试下载速度…"等),让用户知道测试进行到哪一步了。
按钮样式:圆角30的胶囊形按钮,横向padding较大让按钮看起来更宽。
Controller层的测试逻辑
测试过程分为三个阶段:延迟测试、下载测试、上传测试:
class SpeedTestController extends GetxController {
final isTesting = false.obs;
final downloadSpeed = 0.0.obs;
final uploadSpeed = 0.0.obs;
final ping = 0.obs;
final progress = 0.0.obs;
final testPhase = ''.obs;
void startTest() async {
isTesting.value = true;
progress.value = 0;
downloadSpeed.value = 0;
// SpeedTestController定义测试相关的所有响应式状态变量。
// isTesting控制测试状态,progress控制进度条进度。
// downloadSpeed、uploadSpeed、ping分别存储三项测试结果。
uploadSpeed.value = 0;
ping.value = 0;
// 阶段1:测试延迟
testPhase.value = '测试延迟...';
await Future.delayed(const Duration(seconds: 1));
ping.value = 25;
progress.value = 0.2;
// 阶段2:测试下载速度
testPhase.value = '测试下载速度...';
for (int i = 0; i < 10; i++) {
await Future.delayed(const Duration(milliseconds: 200));
// startTest方法启动测试,首先重置所有状态变量。
// 阶段1测试延迟,模拟1秒后得到25ms的延迟结果。
// 阶段2测试下载速度,循环10次模拟速度逐渐增加的效果。
downloadSpeed.value = (i + 1) * 12.5;
progress.value = 0.2 + (i + 1) * 0.04;
}
// 阶段3:测试上传速度
testPhase.value = '测试上传速度...';
for (int i = 0; i < 10; i++) {
await Future.delayed(const Duration(milliseconds: 200));
uploadSpeed.value = (i + 1) * 4.5;
progress.value = 0.6 + (i + 1) * 0.04;
}
testPhase.value = '测试完成';
isTesting.value = false;
// 每次循环更新downloadSpeed和progress,让仪表盘有动画效果。
// 阶段3测试上传速度,逻辑与下载测试类似。
// 测试完成后设置testPhase为"测试完成",isTesting设为false。
}
}
模拟测试过程:用Future.delayed模拟网络请求的耗时,循环更新速度值让仪表盘有动画效果。
进度分配:延迟测试占20%,下载测试占40%,上传测试占40%。每个阶段内部再细分进度。
实际项目中的实现:真正的网速测试需要向测速服务器发送请求,计算数据传输的实际速度。可以使用专门的测速API,或者自己搭建测速服务器。
页面整体结构
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppTheme.backgroundColor,
appBar: AppBar(title: const Text('网络测速')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
_buildSpeedometer(),
SizedBox(height: 40.h),
_buildResults(),
// build方法返回Scaffold,设置背景色和AppBar标题。
// body使用Center让内容居中显示。
// Column使用mainAxisAlignment.center垂直居中排列子组件。
SizedBox(height: 40.h),
_buildStartButton(),
],
),
),
);
}
整个内容居中显示,用Center和MainAxisAlignment.center实现。三个区块之间用40像素的间距分隔。
可以优化的地方
历史记录:保存每次测试的结果,让用户可以查看历史测速记录,对比不同时间、不同网络的速度。
测速服务器选择:提供多个测速服务器让用户选择,不同服务器的测试结果可能有差异。
网络类型显示:在测试前显示当前连接的是WiFi还是移动数据,以及信号强度。
分享功能:测试完成后可以生成一张测速结果图片,方便用户分享到社交媒体。
网速测试功能虽然不复杂,但动画效果和用户反馈做好了,能给用户很好的体验。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
更多推荐



所有评论(0)