Android App優化之高效網路請求

anly_jun發表於2016-10-11

Android App優化之高效網路請求
第一次嘗試直接在掘金上寫文, 效果如何, 就看這個了.

引言

  1. 背景:Android App優化, 要怎麼做?
  2. App優化之效能分析工具
  3. App優化之提升你的App啟動速度之理論基礎
  4. App優化之提升你的App啟動速度之例項挑戰
  5. App優化之Layout怎麼擺
  6. App優化之ANR詳解
  7. App優化之消除卡頓
  8. App優化之記憶體優化
  9. App優化之持久電量
  10. App優化之如何高效網路請求

網際網路時代, App作為於使用者互動的端, 可以說實際上是一個介面, 產品的業務, 服務都是由Server提供的. 而App與Server的互動依賴於網路, 故而網路優化, 也是我們的App優化中不可缺少的一個優化項.

1, 網路連線對使用者的影響

App的網路連線對於使用者來說, 影響很多, 且多數情況下都很直觀, 直接影響使用者對這個App的使用體驗. 其中較為重要的幾點:

  • 流量
    App的流量消耗對使用者來說是比較敏感的, 畢竟流量是花錢的嘛. 現在大部分人的手機上都有安裝流量監控的工具App, 用來監控App的流量使用. 如果我們的App這方面沒有控制好, 會給使用者不好的使用體驗.

  • 電量
    電量相對於使用者來說, 沒有那麼明顯. 一般使用者可能不會太注意. 但是如前文電量優化中說的那樣, 網路連線(radio)是對電量影響很大的一個因素. 所以我們也要加以注意.

  • 使用者等待
    也就是使用者體驗, 良好的使用者體驗, 才是我們留住使用者的第一步. 如果App請求等待時間長, 會給使用者網路卡, 應用反應慢的感覺, 如果有對比, 有替代品, 我們的App很可能就會被使用者無情拋棄.

2, 分析網路連線的工具

2.1 Network Monitor

Android Studio內建的Monitor工具中就有一個Network Monitor:

Android App優化之高效網路請求

其中:

  • Rx --- R(ecive) 表示下行流量, 即下載接收.
  • Tx --- T(ransmit) 表示上行流量, 即上傳傳送.

怎麼使用Network Monitor?

Network monitor實時跟蹤選定應用的資料請求情況. 我們可以連上手機, 選定除錯應用程式, 然後在App上操作我們需要分析的頁面請求.

例如, 上圖就是以CoderPub為例, 針對從repo列表介面進入repo詳情介面的監控資料.

可以看到從10s到30s之間, 20s時間內發生了多次資料請求, 且22s到27s之間的請求資料量還很大.

分析程式碼可以看到, 在請求repo詳情的時候是打包了很多請求的:

@Override
public Observable<RepoDetail> getRepoDetail(String owner, String name) {
    return Observable.zip(mRepoService.get(owner, name),
            mRepoService.contributors(owner, name),
            mRepoService.listForks(owner, name, "newest"),
            mRepoService.readme(owner, name),
            isStarred(owner, name),
            new Func5<Repo, ArrayList<User>, ArrayList<Repo>, Content, Boolean, RepoDetail>() {
                @Override
                public RepoDetail call(Repo repo, ArrayList<User> users, ArrayList<Repo> forks, Content readme, Boolean isStarred) {
                    RepoDetail detail = new RepoDetail();

                    repo.setStarred(isStarred);
                    detail.setBaseRepo(repo);
                    detail.setForks(forks);

                    // because the readme content is encode with Base64 by github.
                    readme.content = StringUtil.base64Decode(readme.content);
                    detail.setReadme(readme);

                    detail.setContributors(users);
                    return detail;
                }
            });
}複製程式碼

這也驗證了14s到20s間的四次資料請求, 另外由於repo詳情介面會顯示作者以及貢獻者的圖片, 而圖片的資料量相對大, 故而23s到27s間有多次資料量很大的請求發生.

這個實際是有很多優化空間的, 我們稍後再說.

2.2 網路代理工具

一般來說, 網路代理工具有兩個作用:

  1. 截獲網路請求響應包, 分析網路請求
  2. 設定代理網路, 移動App開發中一般用來做不同網路環境的測試, 例如Wifi/4G/3G/弱網等.

代理工具很多, 諸如Wireshark, Fiddler, Charles等, 在此不一一細說了, 使用方法自行問谷歌度娘. :)

3, 哪些方面取優化網路連線

第一節說到了網路請求對App和使用者的影響, 那麼我們怎麼從哪些方面去優化網路進而減少甚至消滅這些影響呢?

簡單來說, 兩個方面:

  • 減少Radio活躍時間

    • 也就是減少網路資料獲取的頻次.
    • 這就減少了radio的電量消耗, 控制電量使用.
  • 減少獲取資料包的大小

    • 可以減少流量消耗
    • 也可以讓每次請求更快, 在網路情況不好的情況下也有良好表現, 提升使用者體驗.

那麼, 具體應該從哪些方面著手呢?

3.1 介面設計

API設計

App與Server之間的API設計要考慮網路請求的頻次, 資源的狀態等. 以便App可以以較少的請求來完成業務需求和介面的展示.

例如, 註冊登入. 正常會有兩個API, 註冊和登入, 但是設計API時我們應該給註冊介面包含一個隱式的登入. 來避免App在註冊後還得請求一次登入介面(有可能失敗, 從而導致業務流程失敗).

再例如, 上文提到的獲取repo詳情, 實際上請求了4個介面, 請求了repo的資訊, forks列表, contributors列表, readme, 這是因為github提供的介面是儘量單一職責的. 然而在我們的實際開發中, 我們的Server除了提供這些單一職責的小介面外, 最好還能組合一個滿足客戶端業務需求的repo詳情介面出來.

Gzip壓縮

使用Gzip來壓縮request和response, 減少傳輸資料量, 從而減少流量消耗.

考慮使用Protocol Buffer代替JSON

從前我們傳輸資料使用XML, 後來使用JSON代替了XML, 很大程度上也是為了可讀性和減少資料量(當然還有對映成POJO的方便程度).

Protocol Buffer是Google推出的一種資料交換格式.

如果我們的介面每次傳輸的資料量很大的話, 可以考慮下protobuf, 會比JSON資料量小很多.

當然相比來說, JSON也有其優勢, 可讀性更高.

本文以網路流量優化的角度推薦protobuf作為一個選擇, 具體還需更具實際情況考慮.

圖片的Size

上面Network Monitor中看到的22s到27s之間的有多次請求, 且資料量還很大. 就是在獲取圖片資源.

圖片相對於介面請求來說, 資料量要大得多. 故而也是我們需要優化的一個點.

我們可以在獲取圖片時告知伺服器需要的圖片的寬高, 以便伺服器給出合適的圖片, 避免浪費.

我們現在很多公司的圖片資源都是使用第三方的雲端儲存服務的(七牛, 阿里雲端儲存之類的).

以七牛為例, 可以在請求圖片的url中新增諸如質量, 格式, width, height等path來獲取合適的圖片資源:

imageView2/<mode>/w/<LongEdge>
                 /h/<ShortEdge>
                 /format/<Format>
                 /interlace/<Interlace>
                 /q/<Quality>
                 /ignore-error/<ignoreError>複製程式碼

參考七牛官方文件.

3.2 網路快取

適當的快取, 既可以讓我們的應用看起來更快, 也能避免一些不必要的流量消耗.

關於Android App的網路快取, 請參考MVP架構實現的Github客戶端(4-加入網路快取)一文.

3.3 打包網路請求

當介面設計不能滿足我們的業務需求時. 例如可能一個介面需要請求多個介面, 或是網路良好, 處於Wifi狀態下時我們想獲取更多的資料等.

這時就可以打包一些網路請求, 例如請求列表的同時, 獲取Header點選率較高的的item項的詳情資料.

可以通過一些統計資料來幫助我們定位使用者接下來的操作是高概率的, 提前獲取這部分的資料.

3.4 監聽相關狀態

通過監聽裝置的狀態:

  • 休眠狀態
  • 充電狀態
  • 網路狀態

結合JobScheduler來根據實際情況做網路請求. 比方說Splash閃屏廣告圖片, 我們可以在連線到Wifi時下載快取到本地; 新聞類的App可以在充電, Wifi狀態下做離線快取.

3.5 弱網測試&優化

除了正常的網路優化, 我們還需考慮到弱網情況下, App的表現.

3.5.1 弱網測試

有幾種方式來模擬弱網進行測試.

Android Emulator

建立和啟動Android模擬器可以設定網路速度和延遲:

建立時:

Android App優化之高效網路請求

啟動時, 使用emulator命令:

$emulator -netdelay gprs -netspeed gsm -avd Nexus_5_API_22複製程式碼

具體引數參考這裡這裡, 需要翻牆.

使用網路代理工具

Charles為例:
保持手機和PC處於同一個區域網, 在手機端wifi設定高階設定中設定代理方式為手動, 代理ip填寫PC端ip地址, 埠號預設8888.

Android App優化之高效網路請求

Android App優化之高效網路請求

其他模擬弱網方式

如果你恰好也是iOS的開發者, Apple提供了Network Link Conditioner, 非常好用.

可以模擬的網路情況與上述類似:

Android App優化之高效網路請求
ios_network

如果你使用Linux環境開發, 還可以試下facebook出的ATC.

3.5.2 弱網優化

利用上述工具模擬弱網, 在弱網情況下體驗我們的App. 一般來說, 網路延遲在60ms內, 是OK的, 超過200ms就比較糟糕了. 我們需要做的是在比較糟糕的網路環境下還能給使用者較好的體驗.

弱網優化, 本質上是在弱網的情況下能讓使用者流暢的使用我們的App. 我們要做的就是結合上述的優化項:

  • 壓縮/減少資料傳輸量
  • 利用快取減少網路傳輸
  • 針對弱網(行動網路), 不自動載入圖片
  • 介面先反饋, 請求延遲提交
    例如, 使用者點贊操作, 可以直接給出介面的點贊成功的反饋, 使用JobScheduler在網路情況較好的時候打包請求.

結語

網路優化, 是App優化中相當重要的一項優化. 除了客戶端, 介面的優化外, 很多一部分優化還依賴於伺服器端, 包括伺服器端的程式碼開發, 部署方式等. 跟你的伺服器開發/運維工程師一起聊聊這個話題吧:)

理論上這個應該是App優化系列的最後一篇, 慣例得做些總結啊. 但是如前面記憶體優化所言, 記憶體優化的相關東西將單拎出來, 但是還是會作為本系列的延續. 到時再總結吧.


轉載請註明出處, 歡迎大家分享到朋友圈, 微博~

相關文章