<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                > 編寫:[kesenhoo](https://github.com/kesenhoo) - 原文:[http://developer.android.com/training/efficient-downloads/efficient-network-access.html](http://developer.android.com/training/efficient-downloads/efficient-network-access.html) 使用無線電波(wireless radio)進行傳輸數據這一行為也許是我們app最耗電的操作之一。為了最小化網絡連接對電量消耗,懂得連接模式(connectivity model)會如何影響底層的無線電硬件設備是至關重要的。這節課介紹了無線電波狀態機(wireless radio state machine),并解釋了app的connectivity model是如何與狀態機進行交互的。然后會提出建議的方法來最小化我們的數據連接,使用預取(prefetching)與捆綁(bundle)的方式進行數據的傳輸,這些操作都是為了最小化電量的消耗。 ### 1)The Radio State Machine 一個完全活動的無線電會大量消耗電量,因此需要學習如何在不同狀態下進行過渡,這樣能夠避免電量的浪費。典型的3G無線電網絡有三種能量狀態: - **Full power**: 當無線連接被激活的時候,允許設備以最大的傳輸速率進行操作。 - **Low power**: 一種中間狀態,對電量的消耗差不多是Full power狀態下的50%。 - **Standby**: 最低的狀態,沒有數據連接需要傳輸。 在最低并且空閑的狀態下,電量消耗相對來說是少的。這里需要介紹一延時(latency)的機制,從low status返回到full status大概需要花費1.5秒,從idle status返回到full status需要花費2秒。為了最小化延遲,狀態機使用了一種后滯過渡到更低能量狀態的機制。下圖是一個典型的3G無線電波狀態機的圖示(AT&T電信的一種制式). ![mobile_radio_state_machine.png](https://box.kancloud.cn/2015-07-28_55b724717a065.png "Figure 1. Typical 3G wireless radio state machine.") - 在每一臺設備上的無線狀態機都會根據無線電波的制式(2G,3G,LTE等)而改變,并且由設備本身自己所使用的網絡進行定義與配置。 - 這一課描述了一種典型的3G無線電波狀態機,[data provided by AT&T](http://www.research.att.com/articles/featured_stories/2011_03/201102_Energy_efficient?fbid=SYuI20FzBum)。這些原理是具有通用性的,在其他的無線電波上同樣適用。 - 這種方法在瀏覽通常的網頁操作上是特別有效的,因為它可以阻止用戶在瀏覽網頁時的一些不必要的浪費。而且相對較短的后期處理時間也保證了當一個session結束的時候,無線電波可以轉移到相對較低的能量狀態。 - 不幸的是,這個方法會導致在現代的智能機系統例如Android上的apps效率低下。因為Android上的apps不僅僅可以在前臺運行,也可以在后臺運行。(無線電波的狀態改變會影響到本來的設計,有些想在前臺運行的可能會因為切換到低能量狀態而影響程序效率。坊間說手機在電量低的狀態下無線電波的強度會增大好幾倍來保證信號,可能與這個有關。) ### 2)How Apps Impact the Radio State Machine 每一次新創建一個網絡連接,無線電波就切換到full power狀態。在上面典型的3G無線電波狀態機情況下,無線電波會在傳輸數據時保持在full power的狀態,結束之后會有一個附加的5秒時間切換到low power,再之后會經過12秒進入到low energy的狀態。因此對于典型的3G設備,每一次數據傳輸的會話都會引起無線電波都會持續消耗大概20秒的能量。 實際上,這意味著一個app傳遞1秒鐘的unbundled data會使得無線電波持續活動18秒(18=1秒的傳輸數據+5秒過渡時間回到low power+12秒過渡時間回到standby)。因此每一分鐘,它會消耗18秒high power的電量,42秒的low power的電量。 通過比較,如果每分鐘app會傳輸bundle的data持續3秒的話,其中會使得無線電波持續在high power狀態僅僅8秒鐘,在low power狀態僅僅12秒鐘。上面第二種傳輸bundle data的例子,可以看到減少了大量的電量消耗。圖示如下: ![graphs.png](https://box.kancloud.cn/2015-07-28_55b7247185174.png "Figure 2. Relative wireless radio power use for bundled versus unbundled transfers.") ### 3)Prefetch Data 預取(Prefetching)數據是一種減少獨立數據傳輸會話數量的有效方法。預取技術指的是在一定時間內,單次連接操作,以最大能力下載的情況下,下載所有用戶可能需要的數據。 通過前面的傳輸數據的技術,減少了大量下載數據所需的無線電波激活時間。這樣不僅保存了電量,也降低了帶寬,減少了下載時間。 預取技術通過減少了用戶閱讀所需等待的時間,提高了用戶體驗。 然而,過于頻繁的預取技術的使用,不僅僅會導致電量消耗快速增長,還有可能預取到一些并不需要的數據。同樣,確保app不會因為等待預取全部完成而卡到程序的開始播放也是非常重要的。從實踐的角度,那意味著需要逐步處理數據,并且按照有優先級的順序開始進行數據傳遞,這樣能確保不卡到程序的開始播放的同時數據也能夠得到持續的下載。 那么應該如何控制預取的操作呢?這需要根據正在下載的數據大小與可能被用到的數據量來決定。一個基于上面狀態機情況的比較大概的建議是:對于數據來說,大概有50%的機會可能用在當前用戶的會話中,那么我們可以預取大約6秒(大約1-2Mb),這大概使得潛在可能要用的數據量與可能已經下載好的數據量相一致。 通常來說,預取1-5Mb會比較好,這種情況下,我們僅僅只需要每隔2-5分鐘開始另一段下載。根據這個原理,大數據的下載,比如視頻文件,應該每隔2-5分鐘開始另一段下載,這樣能有效的預取到下面幾分鐘內的數據進行預覽。 值得注意的是,下載需要是bundled的形式,而且上面那些大概的數據與時間可能會根據網絡連接的類型與速度有所變化,這些都將在下面兩部分內容講到。 讓我們來看一些例子: **A music player**你可以選擇預取整個專輯,然而這樣用戶在第一首歌曲之后停止監聽,那么就浪費了大量的帶寬于電量。一個比較好的方法是維護一首歌曲的緩沖區。對于流媒體音樂,不應該去維護一段連續的數據流,因為這樣會使得無線電波一直保持激活狀態,應該考慮把HTTP的數據流集中一次傳輸到音頻流,就像上面描述的預取技術一樣(下載好2Mb,然后開始一次取出,再去下載下面的2Mb)。 **A news reader**許多news apps嘗試通過只下載新聞標題來減少帶寬,完整的文章僅在用戶想要讀取的時候再去讀取,而且文章也會因為太長而剛開始只顯示部分信息,等用戶下滑時再去讀取完整信息。使用這個方法,無線電波僅僅會在用戶點擊更多信息的時候才會被激活。但是,在切換文章分類預閱讀文章的時候仍然會造成大量潛在的消耗。 一個比較好的方法是在啟動的時候預取一個合理數量的數據,比如在啟動的時候預取一些文章的標題與縮略圖信息。之后開始獲取剩余的標題預縮略信息。 另一個方法是預取所有的標題,縮略信息,文章文字,甚至是所有文章的圖片-根據既設的后臺程序進行逐一獲取。這樣做的風險是花費了大量的帶寬與電量去下載一些不會閱讀到的內容,因此這需要比較小心思考是否合適。其中的一個解決方案是,當在連接至Wi-Fi時有計劃的下載所有的內容,并且如果有可能最好是設備正在充電的時候。關于這個的細節的實現,我們將在后面的課程中涉及到。 ### 4)Batch Transfers and Connections 使用典型3G無線網絡制式的時候,每一次初始化一個連接(與需要傳輸的數據量無關),都有可能導致無線電波持續花費大約20秒的電量。 一個app,若是每20秒進行一次ping server的操作,假設這個app是正在運行且對用戶可見,那么這會導致無線電波不確定什么時候被開啟,這樣即使在沒有實際數據需要傳輸的情況下,仍可能造成大量電量的花費。 因此,對數據進行bundle操作并且創建一個序列來存放這些bundle好的數據就顯的非常重要。操作正確的話,可以使得大量的數據集中進行發送,這樣使得無線電波的激活時間盡可能的少,同時減少大部分電量的花費。這樣做的潛在好處是盡可能在每次傳輸數據的會話中盡可能多的傳輸數據而且減少了會話的次數。 ### 5)Reduce Connections 重用已經存在的網絡連接比起重新建立一個新的連接通常來說是更有效率的。重用網絡連接同樣可以使得在擁擠不堪的網絡環境中進行更加智能的互動。當可以捆綁所有請求在一個GET里面的時候不要同時創建多個網絡連接或者把多個GET請求進行串聯。 例如,可以一起請求所有文章的情況下,不要根據多個欄目進行多次請求。為進行termination / termination acknowledgement packets的收發,無線電波會在timeout之前保持激活狀,所以如果不需要的連接請立即關閉而不是等待他們timeout。 之前說道,如果過早對一個連接執行關閉操作,會導致后面再次請求時重新建立一個在Server與Client之間的連接,而我們說過要盡量避免建立重復的連接,那么有個有效的折中辦法是不要立即關閉,而是在timeout之前關閉(即稍微晚點卻又不至于到timeout)。 > **Note**:使用HttpUrlConnection,而不是Apache的HttpClient,前者有做response cache. ### 6)Use the DDMS Network Traffic Tool to Identify Areas of Concern The Android [DDMS (Dalvik Debug Monitor Server)](http://developer.android.com/guide/developing/debugging/ddms.html) 包含了一個查看網絡使用詳情的欄目來允許跟蹤app的網絡請求。使用這個工具,可以監測app是在何時,如何傳輸數據的,從而進行代碼的優化。 下圖顯示了傳輸少量的網絡模型,可以看到每次差不多相隔15秒,這意味著可以通過預取技術或者批量上傳來大幅提高效率。 ![DDMS.png](https://box.kancloud.cn/2015-07-28_55b724718f6ad.png "Figure 3. Tracking network usage with DDMS.") 通過監測數據傳輸的頻率與每次傳輸的數據量,可以查看出哪些位置應該進行優化,通常的,圖中顯示的短小的類似釘子形狀的位置,可以進行與附近位置的請求進行做merge的動作。 為了更好的檢測出問題所在,**Traffic Status API**允許你使用**TrafficStats.setThreadStatsTag()**的方法標記數據傳輸發生在某個Thread里面,然后可以手動的使用tagSocket()進行標記到或者使用untagSocket()來取消標記,例如: ~~~ TrafficStats.setThreadStatsTag(0xF00D); TrafficStats.tagSocket(outputSocket); // Transfer data using socket TrafficStats.untagSocket(outputSocket); ~~~ Apache的HttpClient與URLConnection庫可以自動tag sockets使用當前getThreadStatusTag()的值。那些庫在通過keep-alive pools循環的時候也會tag與untag sockets。 ~~~ TrafficStats.setThreadStatsTag(0xF00D); try { // Make network request using HttpClient.execute() } finally { TrafficStats.clearThreadStatsTag(); } ~~~ Socket tagging 是在Android 4.0上才被支持的, 但是實際情況是僅僅會在運行Android 4.0.3 or higher的設備上才會顯示.
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看