我的Android网络优化为什么不行?
前言:为什么网络优化比别人慢?优化那些还不够?应该加强哪里?
1.Android应用为什么需要考虑网络优化,主要基于以下几个原因:
- 流量:App的移动网络流量消耗对用户来说是比较敏感的;
- 电量:网络请求对电量的消耗是比较大的,影响手机的待机时间;
- 用户体验:网络请求是耗时操作,如果App请求等待时间长,会给用户网络卡, 应用反应慢的感觉。
学习地址:Android开发性能优化解析
2.网络性能优化主要从如下几个方面着手:
- 流量消耗
- 网络速度
- 获取数据优化
- 接口设计
- 弱网优化
1.使用本地缓存,减少网络请求 分为几种情况:
- 基本数据:可以使用持久化技术,比如本地数据库,sharedPreference,本地文件,来记录之前请求下来的数据。而且具有一定的过期时效来保证数据的可用性。
- 图片:同样的,在本地缓存和此图片url映射的图片,可以避免图片的网络请求。目前很多优秀的图片加载框架,如Glide,Picasso,Fresco都具备这种能力。
- 文件:如一般的文件,webview里的js,css,html等,当然也要注意过期时效。
比如有一种场景:App 本地数据库缓存有N个表,当老用户卸载重装时,首次检查需要把远端的数据一次性download到本地来,保证两端的一致性。
由于之前必然为每个表设计了一个api,但是在这种场景下,如果还是继续使用这些api的话,就需要N次网络请求,结果不仅会造成N次网络I/O和磁盘写入I/O,还会使得服务端查找性能降低,用户等待时间较长,本地磁盘写入性能降低。
针对这种场景,完全可以设计一个bulk sync api把这些api整合为一个,这样一来客户端只需一次网络I/O即可获取所有数据,服务端查找性能也提升了一个数量级,本地磁盘I/O也可以把此次返回的数据当成一次事务一次性插入数据库中,大大减少了用户等待时间,同时也提升了网络和本地磁盘写入性能。
3.减少网络请求的数据量 当网络请求不可避免的情况下,此时就要考虑如何减少网络请求携带的数据量。
同样也分几种情况:
- 基本数据:使用数据压缩方式,比如protoBuff格式,okhttp开启gzip压缩,支持Http 2.0,使用其头部压缩,二进制格式替代Http 1.1 文本格式的特性。
- 图片:当不得不获取一张本地缓存没有的图片时,就不得不请求服务端获取。此时没有必要使用最高清的大尺寸的原始图片,完全可以针对客户端显示的图片尺寸和屏幕密度,向服务器请求较小的尺寸,和较低质量的图片,服务器通过图片处理,返回符合此参数的图片给客户端进行显示。
- 文件:普通文件可以进行zip打包下发,而如webview需要加载的css,js,html还可以事先使用webpack压缩,然后再zip打包下发。
另外,还有其他一些方式:
- 如okhttp中复用网络连接的方法,当网络请求等待队列中的host和之前的某个结束的请求连接host一致,此时可以直接让此请求复用此网络连接。
- 使用http 2.0的多路复用特性,我们都知道在http 2.0中,使用了stream的概念,使得多个网络请求可以并行发送,不再需要等待上一次请求响应回来再发送下一个请求,从而有效避免了网络请求的排队,提升了整体网络请求速度。
- 当有网络数据需要具备一定的实时性,可以使用长连接方式,比如websocket,http 2.0的方式进行推送,避免通过网络轮询的方式来达到,这样不仅实时性高,而且减少了网络请求次数,提升了用户体验。
- 连接复用:节省连接时间,如开启keep-alive。Android中HttpUrlConnection默认是开启的。
- 请求合并:可以将多个请求合并为一个进行请求。
- 减小请求数据,并压缩:对于post请求,Body可以做Gzip压缩,如日志。
- 精简数据格式:对于后台返回的数据,尽量使用Json来代替XML。
- 数据的增量更新
- 例如, 注册登录. 正常会有两个API, 注册和登录, 但是设计API时我们应该给注册接口包含一个隐式的登录. 来避免App在注册后还得请求一次登录接口(有可能失败, 从而导致业务流程失败)
- 再例如, 上文提到的获取repo详情, 实际上请求了4个接口, 请求了repo的信息, forks列表, contributors列表, readme, 这是因为github提供的接口是尽量单一职责的. 然而在我们的实际开发中, 我们的Server除了提供这些单一职责的小接口外, 最好还能组合一个满足客户端业务需求的repo详情接口出来。
使用Gzip来压缩request和response, 减少传输数据量, 从而减少流量消耗。
考虑使用Protocol Buffer代替JSON
从前我们传输数据使用XML, 后来使用JSON代替了XML, 很大程度上也是为了可读性和减少数据量(当然还有映射成POJO的方便程度)。
Protocol Buffer是Google推出的一种数据交换格式。
如果我们的接口每次传输的数据量很大的话, 可以考虑下protobuf, 会比JSON数据量小很多。当然相比来说, JSON也有其优势, 可读性更高。
3.图片的Size
上面Network Monitor中看到的22s到27s之间的有多次请求, 且数据量还很大. 就是在获取图片资源。图片相对于接口请求来说, 数据量要大得多. 故而也是我们需要优化的一个点。
我们可以在获取图片时告知服务器需要的图片的宽高, 以便服务器给出合适的图片, 避免浪费。现在很多公司的图片资源都是使用第三方的云存储服务的(七牛, 阿里云存储之类的)
以七牛为例, 可以在请求图片的url中添加诸如质量, 格式, width, height等path来获取合适的图片资源:
文章图片
五丶弱网优化 1.弱网标准 百度其中就有使用的是一个循序渐进的过程,通过三个阶段来建立一个弱网标准。
- 第一阶段,线下测试:
获取预期的阈值,在测试App网络切换、DNS故障时,抓取这些数据
- 第二阶段,线上进行验证:
通过线下获取到的阈值,在线上可以获取到弱网的比例,找到会出现弱网的场景,进行诊断优化。(比如网络体验最好的微信,也只是在信令的传输上优化到极致)
- 第三阶段,线上反复试验:
通过反复试验来调整阈值,使得优化更接近业务层。
腾讯的做法也大同小异,都是根据2.2的指标进行数据收集,整理一套达到弱网时的数据标准。但是我们该如何去探测这些数据呢?这需要我们实现一套完整的网络探测架构。
3.主动网络探测 主动检测,就是在触发了某些特定条件后,主动的进行网络检测,并按照一定的条件检查出是否为弱网状态。架构图如下所示:
文章图片
4.弱网优化 利用工具模拟弱网, 在弱网情况下体验我们的App. 一般来说, 网络延迟在60ms内, 是OK的, 超过200ms就比较糟糕了. 我们需要做的是在比较糟糕的网络环境下还能给用户较好的体验。
弱网优化, 本质上是在弱网的情况下能让用户流畅的使用我们的App. 我们要做的就是结合上述的优化项:
- 压缩/减少数据传输量
- 利用缓存减少网络传输
- 针对弱网(移动网络), 不自动加载图片
- 界面先反馈, 请求延迟提交
例如, 用户点赞操作, 可以直接给出界面的点赞成功的反馈, 使用JobScheduler在网络情况较好的时候打包请求
自己也是从事Android开发5年有余了;整理了一些Android开发技术核心笔记:
更多技术在免费Android技术丶面试题纲丶核心笔记资料
推荐阅读
- Android开发|卡顿(你Android UI优化学好了吗?)
- Android开发|为什么做内存优化,优化着手点在哪里()
- Android开发|ASM与JAVASSIST区别在哪()
- Android布局|如何实战一个Android UI布局,这篇带你玩转UI
- Android|『查漏补缺』Android实习面试知识点(二)
- Android|『查漏补缺』Android实习面试知识点(一)
- Android|『基础巩固』---清晰图解深度分析HTTPS原理
- Android|Android2023暑期实习---网易游戏一面面经
- Android|Android----banner使用详解