引言
1. Android性能优化篇之内存优化--内存泄漏
2.Android性能优化篇之内存优化--内存优化分析工具
3.Android性能优化篇之UI渲染性能优化
4.Android性能优化篇之计算性能优化
5.Android性能优化篇之电量优化(1)——电量消耗分析
6.Android性能优化篇之电量优化(2)
7.Android性能优化篇之网络优化
8.Android性能优化篇之Bitmap优化
9.Android性能优化篇之图片压缩优化
10.Android性能优化篇之多线程并发优化
11.Android性能优化篇之数据传输效率优化
12.Android性能优化篇之程序启动时间性能优化
13.Android性能优化篇之安装包性能优化
14.Android性能优化篇之服务优化
介绍
现在电脑,手机是我们生活中不可或缺的一部分,我们可以随时上网,了解世界各地发生了什么事?包括政治,环境,生活,风景,趣闻等等,同时也可以观看最新的电影,图片,小说,接触到最先进的技术文档等等。网络让我们生活丰富多彩。我们今天就来一起探讨android的网络优化。
一.为什么要对网络进行优化?
1.流量,虽然现在的wifi已经很普及,但还是有需要使用2G/3G/4G的的情况,那么流量是我们必须考虑的一部分(流量不便宜呀)
2.电量(重点),电量是我们需要认真考虑的一方面,手机的续航能力是现在用户关注的一个点,如果手机电量消耗过快,用户可能会卸载那些消耗电量过大的应用。
3.响应时间(重点),用户的体验是我们应用第一个目标,只有给用户好的体验,才能防止用户的流失。
4.安全(重点),网络数据传输的安全,是我们必须面对的一个问题,保护用户信息和数据的安全是我们的职责。
二.网络分析工具
1. Network Monitor 介绍
Network Monitor 是Android Studio内置的网络监控工具。
image4.png
Rx --- Recive 表示下行流量
Tx --- Transmit 表示上行流量2. 代理工具
1.截获网络请求响应包, 分析网络请求
2.设置代理网络
我用的是windows所以 一直使用的是 Fiddler工具3. 模拟弱网
使用Fiddler工具来模拟:查看
三.网络优化方案
我们从任务的集中处理,传输数据优化,安全几个方面来讲解,最后在给出弱网情况下的一些建议
1.任务集中处理,节省流量,降低电量消耗
这段内容在电量优化中已经讲过,这里不再重复太多,就对JobScheduler的使用在扩展下:
JobInfo mJobInfo = new JobInfo.Builder(mJobID, new ComponentName(this, JobWakeUpService.class))
.setPeriodic(mIntervalMillis)//执行周期
.setMinimumLatency(mMinLatencyMillis)//最小延时
.setOverrideDeadline(mMaxExecutionDelayMillis)//最大执行时间
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)//网络类型 NETWORK_TYPE_UNMETERED(wifi 蓝牙)
.setRequiresCharging(true) //充电时执行
//设置重试/退避策略 (重试时间,重试时间间隔)
.setBackoffCriteria(mInitialBackoffMillis, JobInfo.BACKOFF_POLICY_LINEAR)
.setPersisted(isPersisted)//设备重启,任务是否保留
.setRequiresDeviceIdle(isDeviceIdle)//设备空闲时
//监听url对应数据变化,触发当前任务执行
.addTriggerContentUri(mUrl)
//数据变化------->任务执行 最大延迟
.setTriggerContentMaxDelay(mDelay)
//更新 延迟
.setTriggerContentUpdateDelay(mUpdateDelay)
.build();
2.传输数据优化,节省流量,响应更快
(1).gzip压缩
gzip 压缩 还是很常见的,在主流的网络访问框架中都有对应的api让你调用,我们以OKHttp为例:
gzip压缩拦截器:
static class GzipRequestInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
okhttp3.Request originalRequest = chain.request();
if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) {
return chain.proceed(originalRequest);
}
okhttp3.Request compressedRequest = originalRequest.newBuilder()
.header("Content-Encoding", "gzip")
.method(originalRequest.method(), gzip(originalRequest.body()))
.build();
return chain.proceed(compressedRequest);
}
private RequestBody gzip(final okhttp3.RequestBody body) {
return new RequestBody() {
@Override
public MediaType contentType() {
return body.contentType();
}
@Override
public long contentLength() {
return -1; // 无法知道压缩后的数据大小
}
@Override
public void writeTo(BufferedSink sink) throws IOException {
BufferedSink gzipSink = Okio.buffer(new GzipSink(sink));
body.writeTo(gzipSink);
gzipSink.close();
}
};
}
}
使用
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(new GzipRequestInterceptor())//开启Gzip压缩
...
.build();
image1.png(2).代替JSON
使用Protocal Buffers,Nano-Proto-Buffers,FlatBuffer来减小序列化的数据的大小
Protocal Buffers,Nano-Proto-Buffers,FlatBuffers等相关知识可以在关于数据传输优化一章阅读,这里不再展开。(3).缓存
三级缓存还是很常用的,disk cache,mem cache,http cache,下面我们来分别聊一聊:
1.http cache
http协议自带的缓存策略,当资源没有修改时,http status 为304,可以看下下面的图:
ETag 请求变量的实体标签的当前值
Last-Modified 请求资源的最后修改时间
If-Modified-Since 如果请求的部分在指定时间之后被修改则请求成功,未被修改则返回304代码
If-None-Match 如果内容未改变返回304代码,参数为服务器先前发送的Etag,与服务器回应的Etag比较判断是否改变
下面我们来看下Volley关于httpcache的使用:
/**
* 添加头---用于http缓存使用
* @param headers
* @param entry
*/
private void addCacheHeaders(Map<String, String> headers, Cache.Entry entry) {
// If there's no cache entry, we're done.
if (entry == null) {
return;
}
if (entry.etag != null) {
headers.put("If-None-Match", entry.etag);
}
if (entry.lastModified > 0) {
Date refTime = new Date(entry.lastModified);
headers.put("If-Modified-Since", DateUtils.formatDate(refTime));
}
}
2.mem cache
对于请求的是字符串或者json等文本的格式,是不需要内存缓存的。只有请求的是图片时才需要内存缓存对图片进行管理。对图片的管理使用LRU算法来进行管理,关于这方面的知识可以上网查看网上有好多。
3.disk cache
disk 缓存的实现大多数开源框架都是使用的jackwharton的杰作DiskLruCache,如果想要了解更多,可以上网进行查找。
(4).图片压缩
关于图片压缩就不再这里展开,后面会有单独的一章来讲解。
image3.png3.不同的网络状况,做不同的事
在WiFi,4G,3G等不同的网络下设计不同大小的预取数据量,也可以是按照图片数量或者操作时间来作为阀值,我们还需要把当前的网络环境情况添加到设计预取数据量的策略当中去。判断当前设备的状态与网络情况,可以使用JobScheduler.
我们可以把网络请求延迟划分为三档:例如把网络延迟小于60ms的划分为GOOD,大于220ms的划分为BAD,介于两者之间的划分为OK(这里的60ms,220ms会需要根据不同的场景提前进行预算推测)。如果网络延迟属于GOOD的范畴,我们就可以做更多比较激进的预取数据的操作,如果网络延迟属于BAD的范畴,我们就应该考虑把当下的网络请求操作Hold住等待网络状况恢复到GOOD的状态再进行处理。
image2.png
提示:使用AT&T提供的AT&T Network Attenuator来帮助预估网络延迟
4.安全,保护用户信息
主要针对两个问题:
1.保证API的调用者是经过自己授权的App
2.保证数据传输的安全。
第一个问题:我主要采用设计签名的方式。对每个客户端,Android、iOS、WeChat,分别分配一个AppKey和AppSecret。需要调用API时,将AppKey加入请求参数列表,并将AppSecret和所有参数一起,根据某种签名算法生成一个签名字符串,然后调用API时把该签名字符串也一起带上。服务端收到请求之后,根据请求中的AppKey查询相应的AppSecret,按照同样的签名算法,也生成一个签名字符串,当服务端生成的签名和请求带过来的签名一致的时候,那就表示这个请求的调用者是经过自己授权的,证明这个请求是安全的。而且,每个端都有一个Key,也方便不同端的标识和统计。为了防止AppSecret被别人获取,这个AppSecret一般写死在代码里面。另外,签名算法也需要有一定的复杂度,不能轻易被别人破解,最好是采用自己规定的一套签名算法,而不是采用外部公开的签名算法。另外,在参数列表中再加入一个时间戳,还可以防止部分重放攻击。
第二个问题:主要就是采用HTTPS了。HTTPS因为添加了SSL安全协议,自动对请求数据进行了压缩加密,在一定程序可以防止监听、防止劫持、防止重发,主要就是防止中间人攻击。苹果从iOS9开始,默认就采用HTTPS了。而关于在Android中如何使用HTTPS,Google官方也给出了很多安全建议。不过,大部分App并没有按照安全建议去实现,主要就是没有对SSL证书进行安全性检查,这就成为了一个很大的漏洞,中间人利用此漏洞用假证书就可以通过检查,从而可以劫持到所有数据了。因此,为了安全考虑,建议对SSL证书进行强校验,包括签名CA是否合法、域名是否匹配、是不是自签名证书、证书是否过期等。5.弱网情况下我们应该做些什么?
(1).压缩/减少数据传输量
(2).利用缓存减少网络传输
(3).针对弱网(移动网络), 不自动加载图片
(4).界面先反馈, 请求延迟提交
网友评论