弱网优化空间探索

[toc]

第3节:弱网优化空间探索

前言

在前一节 弱网测试 中,我们罗列了网络测试的各种问题。而本节我们针对弱网单独的进行说明。

本节的其他参考文章:

背景

弱网下:如何让我们的app不受弱网的影响,以使得用户能够继续”正常”使用我们的网络?

1、网络优化的必要性分析/竞品分析

通过竞品分析,App网络测试&竞品对比.xlsx,测试各APP在各相同网络环境下的表现。对存在的不足进行发现和优化。

看看其他APP都是在什么网络(什么值)下大概不行?

最佳网络质量 开始出现问题 基本不可用的网络
带宽(kbps) > > & < > & <
丢包率(%) < > & < > & <
延迟(ms) < > & < > & <

2、网络优化的切入点整理(开始前、执行中、完成后)

对此我们从弱网下的事件开始前、事件执行中及事件执行结束对结果的处理三个阶段来分析。

阶段 概述 处理位置 优化方案
1 弱网下,事件开始前可考虑的优化 数据上 用户体验优化 + 网络状态/网络质量
2 弱网下,事件执行过程中可考虑的优化 数据上 缓存 + 降低质量
3 弱网下,事件执行结束对结果的处理可考虑的优化 界面上 UI和Toast的显示

一、弱网下,事件开始前可考虑的优化

1、进入页面时候就优化用户体验,避免弱网无数据的页面异常

下图摘自:《用户加载体验优化》中的【一、页面初始加载优化】

image-20240725001944956

从上图中,可以看出弱网情况下,我们可以针对不同的网络:做不同超时,重试设置,以及取不同质量的图片数据。

2、事件开始前,网络状态、质量的获取、同步及联动

1、网络类型从wifi切换到移动网络/无网络时,全局Toast提示用户当前联网类型切换为移动网络/无网络。

2、弱网情况下(下行网络质量低于某个阀值)提示用户当前网络较差,请检查网络状态。

二、弱网下,事件执行结束对结果的处理可考虑的优化

弱网下的事件结果,主要体现在界面上。尤其是UI提示、toast提示

1、弱网问题在界面上的体现 UI/toast的显示不同存、不同失

针对请求超时/请求失败,常见的提示方式有UI提示、或者toast提示。而常出现的可考虑优化的场景如下:

序号 问题类型/可优化点 优化建议 优化方案具体描述
1 弱网view、弱网toast同时都存在 只保留弱网view 请求接口时,自己处理业务失败的toast,而非底层自动toast
接口异常:①业务异常仍然toast、②超时异常去除toast
2 弱网view、弱网toast同时不存在 至少有弱网toast 页面接口请求可允许使用底层自动toast机制
3 同接口弱网超时,连弹弱网toast 优化连弹/重叠 接口针对异常区分超时类型,toast使用对应单例优化连弹但不重弹
4 弱网超时\无网,页面空数据兼容 兼容空数据 ①补充空页面
②点击无反应 –> 改为提示”后台数据异常”

为了找到确实需要处理的优化点,我们可以在以下表格中先整体罗列弱网下的所有可能是异常的页面,然后再评估哪些需要处理。表格样式如下:

优化点概述 优化点详细说明 待优化处截图/视频 页面路径 错误重现 是否需要处理 备注 状态

待优化处截图/视频示例:

ui_toast_both

ui_toast_none

2、toast提示语尽量后台化

1、提取APP中现有的本地toast。

为此我专门写了个脚本:获取文本中的某些文本并将其整理到excel中:https://gitee.com/dvlpCI/package-size-resource/blob/master/Flutter/example_get_file_some_text.sh

整理的表格完成版示例如下:

https://gitee.com/dvlpCI/package-size-resource/blob/master/Flutter/APP提示语清单表.xlsx

APP提示语清单表:

文件(简) 行号 提示文案 文案类型 触发路径及条件 提示方式 isUse 是否使用中
(//判断)
创建者 修改者
xxx_page.dart 128 复制成功 成功 TRUE
xxx_page.dart 81 抱歉:图片上传失败 失败 TRUE
xxx_page.dart 105 请选择物流公司 提示 TRUE
xxx_page.dart 891 正在开发中… 未确定 TRUE

三、弱网下,事件执行过程中可考虑的优化

网络区分的方式,主要有网络类型、网络质量。

1、网络类型、网络质量必备基础知识

切入点类型(及其原理) 适用的使用场景 参考文档
1 实时检测网络类型变化
(移动网络、wifi网络、无网络)
可在网络类型变化,提示用户注意当前网络环境 connectivity_plus Flutter检查连接网络connectivity_plus实现步骤
2 检测网络的可达性和网络延迟时间,探测信号强度。附:Ping测试不能测量网络的带宽容量,只反映延迟。
原理:通过发送ICMP(Internet Control Message Protocol)回显请求到服务器,并测量回显响应的时间,来评估网络的延迟(Ping值)。
dart_ping Flutter Ping检查服务器通讯信号强度实现步骤
3.1 测试设备的网络速度(包括上传和下载速度)
原理:从选定的服务器下载一定大小的数据包来测试下载速度。测试时会记录下载所需的时间,并据此计算出下载速度。上传计算同理。
flutter_internet_speed_test 见库自身地址
3.2 测试设备的网络速度(包括上传和下载速度)
NERTC_SDK
NERTC SDK 通话前网络质量探测

附:上述部分库的使用示例详见: 附1:网络类型、网络质量部分库的使用示例

2、网络类型、网络质量在流程中的使用场景

流程中的优化空间:我们以网络类型、网络质量决定体验的原则,来分析,使得在不同网络状态下,可以有不同的用户体验。

image-20230725152850177

体验举例:

处理内容 低弱网下处理 强弱网下处理
图片 加载抵制图:1倍图 直接全不加载
视频 降低清晰度 直接不播放

3、从加载流程看网络质量

我们从页面加载流程探索弱网优化的空间。

image-20230714144045136

其中以上述图片加载渲染流程为例(加载视频同理),其过程如下:

image-20230725152850177

附1:网络类型、网络质量部分库的使用示例

1.1、使用 connectivity_plus,实时检测网络类型变化(移动网络、wifi网络、无网络)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 初始化
Future<void> _init() async {
try {
// 方式1:单次请求检查
// final connectivityResult = await _connectivity.checkConnectivity();
// _updateConnectionStatus(connectivityResult);
// 方式2:状态订阅
_subscription = _connectivity.onConnectivityChanged.listen(_updateConnectionStatus);
} on PlatformException catch (e) {
print(e);
print('连接网络出现了异常');
}
}

Future<void> _updateConnectionStatus(ConnectivityResult result) async {
setState(() {
_connectivityStatus = result;
});
if (result == ConnectivityResult.mobile) {
print('成功连接移动网络');
} else if (result == ConnectivityResult.wifi) {
print('成功连接WIFI');
} else if (result == ConnectivityResult.ethernet) {
print('成功连接到以太网');
} else if (result == ConnectivityResult.vpn) {
print('成功连接vpn网络');
} else if (result == ConnectivityResult.bluetooth) {
print('成功连接蓝牙');
} else if (result == ConnectivityResult.other) {
print('成功连接除以上以外的网络');
} else if (result == ConnectivityResult.none) {
print('没有连接到任何网络');
}
}

1.2、使用 dart_ping 库来执行Ping操作,探测信号强度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
   final ping = Ping('baidu.com', count: 5, interval: 1); // count: ping的次数   interval:每几秒ping一次
ping.stream.listen((event) {
if (event.error != null) {
print("网络较差或网络断开:${event.error.toString()}")
} else {
int pingDelay = event.response?.time?.inMillisecondes ?? 0;
_signalStrength = calculateSignalStrength(pingDelay); // 信号强度
print("网络状态信息:${pingDelay}");
}
});

// 信号强度 0 ~ 5 , 5 最好,0 最差
int calculateSignalStrength(int pingDelay) {
if (pingDelay < 0) return 0; // 无网络连接
if (pingDelay < 100) return 5; // 延迟 < 100ms,信号强度为 5
if (pingDelay < 200) return 4; // 延迟 < 200ms,信号强度为 4
if (pingDelay < 300) return 3; // 延迟 < 300ms,信号强度为 3
if (pingDelay < 500) return 2; // 延迟 < 500ms,信号强度为 2
return 1; // 延迟 >= 500ms,信号强度为 1
}

打印结果:

dart_ping_reslut