前言
好久好久没有在简书上面写东西了,一方面是平时工作太累了,写的笔记潦草,没有整理好分享在这里,一方面是技术还在沉淀中吧,需要学习的地方很多,怕误导了大家。(呃....其实主要原因就是懒,哈哈。)
这里写完这篇文章后,开始换新的工作了。
【by:现在在虎牙直播,部门紧缺人,各种技术岗位,需要帮忙内推的吱一声。】
- 这里立个 flag,换工作后,再把之前的学习笔记,整理一下,多写几篇思路清晰点的文章。 (🙈 希望不打脸)
弱网测试方案
一、Charles
1、Enable Throttling:
iOS 设备设置完代理,打开设置:Proxy -> Throttle Settings → Enable Throttling
后根据场景,设置需要的弱网效果,一般选最低的选项。
2、直接选中龟速
【by:具体的效果以上面 Throttle Settings 的弱网参数为准。(测试完弱网环境记得关闭...)】
二、iOS 设备自带弱网测试
设置-> 开发者 -> Networking Link Conditioner:
参数含:
- In bandwidth 下行带宽
- In packet loss 下行丢包率
- In delay 下行延迟,单位为ms
- Out bandwidth 上行带宽
- Out packet loss 上行丢包率
- Out delay 上行延迟
- DNS delay DNS 解析延迟
- Protocol 协议,包括 Any、IPv4、IPv6
- Interface 接口,可选 ALL、Wi-Fi、cellular(蜂窝网)
(测试完弱网环境记得关闭...)
优化方案
一、必要的状态呈现
弱网优化的目的,是调高用户的使用体验。
所以很重要的一点就是:不同网络加载状态的过程反馈,或"积极"反馈给用户(下文“用户体验优化”里,会提到加载进度从50%起的"积极"反馈做法)。
1、无网络提示。
可为 Controller 监听网络状态的改变:
例如用的 AFNetworking 的 AFNetworkReachabilityStatus。
为无网络状态等进行告知用户的处理。
2、加载前需要添加“正在加载中的动画/视图”
例如 MBProgressHUD 的使用。
3、加载后需要先移除网络状态视图,并增加判定空数据处理。[如有可能,判定是网络原因,还是无数据的原因。]
[hud hideAnimated:YES];
if (数据为空) {
// 这里做空视图处理
}
4、善用状态切换的通知,为界面做出不同的变化。
在 2G、3G、4G、wifi,(现在还有 5g) 等不同的网络做出不同的状态图切换,或者交互切换。
二、网络请求优化
1、制定最合适的超时时间:
对总读写超时(从请求到响应的超时)、首包超时、包包超时(两个数据段之间的超时)时间制定不同的计算方案,加快对超时的判断,减少等待时间,尽早重试。这里的超时时间还可以根据网络状态动态设定,例如在网络状态为 2G、3G、4G、wifi 下设置不同的超时时间。
2、多子模块请求的“延迟性”:
以用户等待容忍度不超过 2s 为原则,像首页这种多个业务模块一起呈现的页面,如果一次性请求完所有的接口数据,估计用户已经 Home 回到主页了,所以可以对多子模块,进行分段的“延迟”请求。
- 优先模块:请求数据量少、业务上需要优先显示的。
- 延后模块:数据量大、类似列表的多条数据,适合放置加载动画,时长上用户可接受性强,所以除了放在后面外,可做分页处理、滑动后的延迟加载处理。
3、固定模块加入缓存机制、或增量更新机制:
对首页及特定一级页面进行数据缓存,在一定的有效时间内再次请求可以直接从缓存读取数据,也可避免空白页出现影响体验。
或者进行判断数据是否有增量变化,有点的话在插入动画的前提下,进行数据的更新。
4、多模块的重新加载操作:
像一些多模块,模块之间相关联的复杂页面,多个模块会有多个请求,当某个请求失败需要添加“重新加载”的按钮时,建议所有请求重新请求一遍,防止模块之间关联的数据出现偏差,或者 UI 布局错乱。
例如,链家的 APP(仅供讨论,无其他意思哈,链家请见谅😬 ),弱网环境下,中间某模块 UI 产生混乱,如果在用户下拉重新加载请求的情况下,如果不是首页这整个模块请求后完,进行布局重新计算,那么后面的 UI 就一直是这个状态。
所以,如果有做网络请求失败后,重新加载的按钮/下拉操作,建议是:
- 多模块再各自请求一遍。
- 复杂 UI 重新计算一下。
原因是:弱网环境,本身请求到的数据可能也不齐全,多个请求或许只能拿到部分数据,而大部分情况是,各模块是相辅相成的。
5、预加载设置“临界值”
使用 Threshold 进行预加载是一种最为常见的预加载方式,知乎客户端就使用了这种方式预加载条目,而其原理也非常简单,根据当前 UITableView 的所在位置,除以目前整个 UITableView.contentView 的高度,来判断当前是否需要发起网络请求:在当前页面已经划过了 70% 的时候,就请求新的资源,加载数据;
但是,仅仅使用这种方法会有另一个问题,尤其是当列表变得很长时,十分明显,会导致新加载的页面都没有看,应用就会发出另一次请求,获取新的资源。
【问题可参照:预加载与智能预加载 (VIA)】
6、从请求这个动作下手:
优化DNS查询:应尽量减少DNS查询,做DNS缓存,避免域名劫持、DNS污染,同时把用户调度到“最优接入点”。
减小数据包大小和优化包量:通过压缩、精简包头、消息合并等方式,来减小数据包大小和包量。
优化ACK包:平衡冗余包和ACK包个数,达到降低延时,提高吞吐量的目的。
这几个,都是在优化请求的数据处理和查询上做优化的。感兴趣的话,可以翻到最下面的资料网翻阅,或通过查询 HTTP 协议,TCP/UDP 协议这部分网络优化内容,分析总结并对网络请求这块进行细致优化。
7、断线重连。
在无线网络中有太多的原因导致数据连接中断了。这里可以使用CDN。
(CDN 是构建在数据网络上的一种分布式的内容分发网。 CDN 的作用是采用流媒体服务器集群技术,克服单机系统输出带宽及并发能力不足的缺点,可极大提升系统支持的并发流数目,减少或避免单点失效带来的不良影响。)
8、减少数据连接的创建次数
由于创建连接是一个非常昂贵的操作,所以应尽量减少数据连接的创建次数,且在一次请求中应尽量以批量的方式执行任务。如果多次发送小数据包,应该尽量保证在2秒以内发送出去。在短时间内访问不同服务器时,尽可能地复用无线连接。
三、用户体验优化
1、内容分先后显示:
例如,一个业务模块文字图片都有的情况。
一个完整的请求和加载,可能一直卡在50%-90%的时候,那么先加载文字,再加载图片。
2、进度的驱使:
不管网络条件如何,加载进度始终是从50%起,并且停留在大约98%进度左右的地方。
(当然, 不建议在数据量比较大的请求中做这样的显示机制,因为会让用户产生网络波动较大的体验。)
3、固定的 UI 显示布局,加载时可预加载虚拟布局视图:
类似知乎。在加载时,“正在加载中的动画/视图”,改为主页面显示预加载的占位图。交互上,数据的加载会让用户对 APP 的 UI 设计有熟悉感。
4、弱网加载失败/空数据,可添加“重新加载”的按钮,或可增加下拉刷新操作。
例如:请求无数据/网络失败,添加‘重新加载“按钮,让用户意识到处于“可控”状态,降低用户焦躁情绪。
四、图片加载优化
1、使用更快的图片格式:
严格说也不算弱网下的优化,但一个更快的图片格式真的很重要!这里建议采用 WebP 格式。(WebP 格式,谷歌(google)开发的一种旨在加快图片加载速度的图片格式。图片压缩体积大约只有 JPEG 的2/3,并能节省大量的服务器带宽资源和数据空间。但 WebP 是一种有损压缩。相较编码 JPEG 文件,编码同样质量的 WebP 文件需要占用更多的计算资源。)
2、根据网络状态呈现不同精度的图:
如(对于原图是 600X480 的图片):
- 2/3G 使用低清晰度图片:下发 300X240,精度为 80 的图片;
- 4G 普通清晰度图片下发 600X480,精度为 80 的图片;
- WiFi 高清晰度图片(最好根据网速来判断,WiFi 也有慢的):下发 600X480,精度为 100 的图片。
4、SDWebImage 参数选项:
根据使用场景,参照 SDWebImageOptions常量说明,对图片的加载进行。
5、干脆不加载图片...
这也是一个方法,弱网情况下,在一些不影响操作,并能通过简单文字的描述告知用户该区域的内容,可以不加载图片,待到网络流畅状态再进行图片的加载。
当然这种方法要视情况而定,或者一般都在 APP 的设置选项,增加一个“弱网状态不显示图片”的按钮。
关于网络加载、弱网优化可参考资料:
【比较全的弱网优化资料:http://www.52im.net/thread-1588-1-1.html】
【短连接的优化手段总结:http://www.52im.net/thread-1413-1-1.html】
【iOS网络深度优化总结://www.greatytc.com/p/a470ab485e39】
(转载请标明原文出处,谢谢支持 ~ - ~)
by:啊左~