引言
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();
(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).圖片壓縮
關于圖片壓縮就不再這里展開,后面會有單獨的一章來講解。
3.不同的網絡狀況,做不同的事
在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).界面先反饋, 請求延遲提交