国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android性能優化典范(第二季)

2019-11-09 17:36:26
字體:
來源:轉載
供稿:網友

0、概述

Android性能優化典范第2季的課程,一共20個短視頻,包括的內容大致有:電量優化,網絡優化,Wear上如何做優化,使用對象池來提高效率,LRU Cache,Bitmap的縮放,緩存,重用,PNG壓縮,自定義View的性能,提升設置alpha之后View的渲染性能,以及Lint,StictMode等等工具的使用技巧。 下面是對這些課程的總結摘要,認知有限,理解偏差的地方請多多指教!

1、Battery Drain and Networking

對于手機程序,網絡操作相對來說是比較耗電的行為。優化網絡操作能夠顯著節約電量的消耗。在性能優化第1季里面有提到過,手機硬件的各個模塊的耗電量是不一樣的,其中移動蜂窩模塊對電量消耗是比較大的,另外蜂窩模塊在不同工作強度下,對電量的消耗也是有差異的。當程序想要執行某個網絡請求之前,需要先喚醒設備,然后發送數據請求,之后等待返回數據,最后才慢慢進入休眠狀態。這個流程如下圖所示:

這里寫圖片描述

在上面那個流程中,蜂窩模塊的電量消耗差異如下圖所示:

這里寫圖片描述

從圖示中可以看到,激活瞬間,發送數據的瞬間,接收數據的瞬間都有很大的電量消耗,所以,我們應該從如何傳遞網絡數據以及何時發起網絡請求這兩個方面來著手優化。

首先我們需要區分哪些網絡請求是需要及時返回結果的,哪些是可以延遲執行的。例如,用戶主動下拉刷新列表,這種行為需要立即觸發網絡請求,并等待數據返回。但是對于上傳用戶操作的數據,同步程序設置等等行為則屬于可以延遲的行為。我們可以通過Battery Historian這個工具來查看關于移動蜂窩模塊的電量消耗。在Mobile Radio那一行會顯示蜂窩模塊的電量消耗情況,紅色的部分代表模塊正在工作,中間的間隔部分代表模塊正在休眠狀態,如果看到有一段區間,紅色與間隔頻繁的出現,那就說明這里有可以優化的行為。如下圖所示:

這里寫圖片描述

對于上面可以優化的部分,我們可以有針對性的把請求行為捆綁起來,延遲到某個時刻統一發起請求。如下圖所示:

這里寫圖片描述

經過上面的優化之后,我們再回頭使用Battery Historian導出電量消耗圖,可以看到喚醒狀態與休眠狀態是連續大塊間隔的,這樣的話,總體電量的消耗就會變得更少。

這里寫圖片描述

當然,我們甚至可以把請求的任務延遲到手機網絡切換到WiFi,手機處于充電狀態下再執行。在前面的描述過程中,我們會遇到的一個難題是如何把網絡請求延遲,并批量進行執行。還好,Android提供了JobScheduler來幫助我們達成這個目標。

2、如何傳遞網絡數據

關于這部分主要會涉及到PRefetch(預取)與Compressed(壓縮)這兩個技術。對于Prefetch的使用,我們需要預先判斷用戶在此次操作之后,后續零散的請求是否很有可能會馬上被觸發,可以把后面5分鐘有可能會使用到的零散請求都一次集中執行完畢。對于Compressed的使用,在上傳與下載數據之前,使用CPU對數據進行壓縮與解壓,可以很大程度上減少網絡傳輸的時間。

想要知道我們的應用程序中網絡請求發生的時間,每次請求的數據量等等信息,可以通過Android Studio中的Networking Traffic Tool來查看詳細的數據,如下圖所示:

這里寫圖片描述

2、Wear 和 Sensors

在Android Wear上會大量的使用Sensors來實現某些特殊功能,如何在盡量節約電量的前提下利用好Sensor會是我們需要特別注意的問題。下面會介紹一些在Android Wear上的最佳實踐典范。

盡量減少刷新請求,例如我們可以在不需要某些數據的時候盡快注銷監聽,減小刷新頻率,對Sensor的數據做批量處理等等。那么如何做到這些優化呢?

首先我們需要盡量使用Android平臺提供的既有運動數據,而不是自己去實現監聽采集數據,因為大多數Android Watch自身記錄Sensor數據的行為是有經過做電量優化的。其次在Activity不需要監聽某些Sensor數據的時候需要盡快釋放監聽注冊。還有我們需要盡量控制更新的頻率,僅僅在需要刷新顯示數據的時候才觸發獲取最新數據的操作。另外我們可以針對Sensor的數據做批量處理,待數據累積一定次數或者某個程度的時候才更新到UI上。最后當Watch與Phone連接起來的時候,可以把某些復雜操作的事情交給Phone來執行,Watch只需要等待返回的結果。

3、Smooth Android Wear Animation

Android Material Design風格的應用采用了大量的動畫來進行UI切換,優化動畫的性能不僅能夠提升用戶體驗還可以減少電量的消耗,下面會介紹一些簡單易行的方法。

在Android里面一個相對操作比較繁重的事情是對Bitmap進行旋轉,縮放,裁剪等等。例如在一個圓形的鐘表圖上,我們把時鐘的指針摳出來當做單獨的圖片進行旋轉會比旋轉一張完整的圓形圖的所形成的幀率要高56%。

這里寫圖片描述

另外盡量減少每次重繪的元素可以極大的提升性能,假如某個鐘表界面上有很多需要顯示的復雜組件,我們可以把這些組件做拆分處理,例如把背景圖片單獨拎出來設置為一個獨立的View,通過setLayerType()方法使得這個View強制用Hardware來進行渲染。至于界面上哪些元素需要做拆分,他們各自的更新頻率是多少,需要有針對性的單獨討論。

用Systrace等工具來查看某些View的渲染性能。

對于大多數應用中的動畫,我們會使用PropertyAnimation或者ViewAnimation來操作實現,Android系統會自動對這些Animation做一定的優化處理,在Android上面學習到的大多數性能優化的知識同樣也適用于Android Wear。

4、Android Wear Data Batching

在Android Training里面有關于Wear上面如何利用Wearable API與Phone進行溝通協作的課程。因為Phone的CPU與電量都比Wear要強大,另外Phone還可以直接接入網絡,而Wear要接入網絡則相對更加困難,所以我們在開發Wear應用的時候需要盡量做到把復雜的操作交給Phone來執行。例如我們可以讓Phone來獲取天氣信息,然后把數據返回Wear進行顯示。更進一步,在之前的性能優化課程里面我們有學習過如何使用JobScheduler來延遲批量處理任務,假設Phone收到來自Wear的其中一個任務是每隔5分鐘檢查一次天氣情況,那么Phone使用JobScheduler執行檢查天氣任務之后,先判斷這次返回的結果和之前是否有差異,僅僅當天氣發生變化的時候,才有必要把結果通知到Wear,或者僅僅把變化的某一項數據通知給Wear,這樣可以更大程度上減少Wear的電量消耗。

下面我們總結一下如何優化Wear的性能與電量:

僅僅在真正需要刷新界面的時候才發出請求盡量把計算復雜操作的任務交給Phone來處理Phone僅僅在數據發生變化的時候才通知到Wear把零碎的數據請求捆綁一起再進行操作

5、Object Pools

在程序里面經常會遇到的一個問題是短時間內創建大量的對象,導致內存緊張,從而觸發GC導致性能問題。對于這個問題,我們可以使用對象池技術來解決它。通常對象池中的對象可能是bitmaps,views,paints等等。關于對象池的操作原理,不展開述說了,請看下面的圖示:

這里寫圖片描述

使用對象池技術有很多好處,它可以避免內存抖動,提升性能,但是在使用的時候有一些內容是需要特別注意的。通常情況下,初始化的對象池里面都是空白的,當使用某個對象的時候先去對象池查詢是否存在,如果不存在則創建這個對象然后加入對象池,但是我們也可以在程序剛啟動的時候就事先為對象池填充一些即將要使用到的數據,這樣可以在需要使用到這些對象的時候提供更快的首次加載速度,這種行為就叫做預分配。使用對象池也有不好的一面,程序員需要手動管理這些對象的分配與釋放,所以我們需要慎重地使用這項技術,避免發生對象的內存泄漏。為了確保所有的對象能夠正確被釋放,我們需要保證加入對象池的對象和其他外部對象沒有互相引用的關系。

13、Batching Background Work Until Later

優化性能時大多數時候討論的都是如何減少不必要的操作,但是選擇何時去執行某些操作同樣也很重要。

為了避免我們的應用程序過多的頻繁消耗電量,我們需要學習如何把后臺任務打包批量,并選擇一個合適的時機進行觸發執行。下圖是每個應用程序各自執行后臺任務導致的電量消耗示意圖:

這里寫圖片描述

因為像上面那樣做會導致浪費很多電量,我們需要做的是把部分應用的任務延遲處理,等到一定時機,這些任務一并進行處理。結果如下面的示意圖:

這里寫圖片描述

1)AlarmManager

使用AlarmManager設置定時任務,可以選擇精確的間隔時間,也可以選擇非精確時間作為參數。除非程序有很強烈的需要使用精確的定時喚醒,否者一定要避免使用他,我們應該盡量使用非精確的方式。

2)SyncAdapter

我們可以使用SyncAdapter為應用添加設置賬戶,這樣在手機設置的賬戶列表里面可以找到我們的應用。這種方式功能更多,但是實現起來比較復雜。我們可以從這里看到官方的培訓課程:http://developer.android.com/training/sync-adapters/index.html

3)JobSchedulor

這是最簡單高效的方法,我們可以設置任務延遲的間隔,執行條件,還可以增加重試機制。

14、Smaller Pixel Formats

常見的png,jpeg,webp等格式的圖片在設置到UI上之前需要經過解碼的過程,而解壓時可以選擇不同的解碼率,不同的解碼率對內存的占用是有很大差別的。在不影響到畫質的前提下盡量減少內存的占用,這能夠顯著提升應用程序的性能。

Android的Heap空間是不會自動做兼容壓縮的,意思就是如果Heap空間中的圖片被收回之后,這塊區域并不會和其他已經回收過的區域做重新排序合并處理,那么當一個更大的圖片需要放到heap之前,很可能找不到那么大的連續空閑區域,那么就會觸發GC,使得heap騰出一塊足以放下這張圖片的空閑區域,如果無法騰出,就會發生OOM。如下圖所示:

這里寫圖片描述

所以為了避免加載一張超大的圖片,需要盡量減少這張圖片所占用的內存大小,Android為圖片提供了4種解碼格式,他們分別占用的內存大小如下圖所示:

這里寫圖片描述

隨著解碼占用內存大小的降低,清晰度也會有損失。我們需要針對不同的應用場景做不同的處理,大圖和小圖可以采用不同的解碼率。在Android里面可以通過下面的代碼來設置解碼率:

這里寫圖片描述

15、Smaller PNG Files

盡量減少PNG圖片的大小是Android里面很重要的一條規范。相比起JPEG,PNG能夠提供更加清晰無損的圖片,但是PNG格式的圖片會更大,占用更多的磁盤空間。到底是使用PNG還是JPEG,需要設計師仔細衡量,對于那些使用JPEG就可以達到視覺效果的,可以考慮采用JPEG即可。我們可以通過Google搜索到很多關于PNG壓縮的工具,如下圖所示:

這里寫圖片描述

這里要介紹一種新的圖片格式:Webp,它是由Google推出的一種既保留png格式的優點,又能夠減少圖片大小的一種新型圖片格式。關于Webp的更多細節,請點擊這里。

16、Pre-scaling Bitmaps

對bitmap做縮放,這也是Android里面最遇到的問題。對bitmap做縮放的意義很明顯,提示顯示性能,避免分配不必要的內存。Android提供了現成的bitmap縮放的API,叫做createScaledBitmap(),使用這個方法可以獲取到一張經過縮放的圖片。

這里寫圖片描述

上面的方法能夠快速的得到一張經過縮放的圖片,可是這個方法能夠執行的前提是,原圖片需要事先加載到內存中,如果原圖片過大,很可能導致OOM。下面介紹其他幾種縮放圖片的方式。

inSampleSize能夠等比的縮放顯示圖片,同時還避免了需要先把原圖加載進內存的缺點。我們會使用類似像下面一樣的方法來縮放bitmap:

這里寫圖片描述

這里寫圖片描述

另外,我們還可以使用inScaled,inDensity,inTargetDensity的屬性來對解碼圖片做處理,源碼如下圖所示:

這里寫圖片描述

還有一個經常使用到的技巧是inJustDecodeBounds,使用這個屬性去嘗試解碼圖片,可以事先獲取到圖片的大小而不至于占用什么內存。如下圖所示:

這里寫圖片描述

17、Re-using Bitmaps

我們知道bitmap會占用大量的內存空間,這節會講解什么是inBitmap屬性,如何利用這個屬性來提升bitmap的循環效率。前面我們介紹過使用對象池的技術來解決對象頻繁創建再回收的效率問題,使用這種方法,bitmap占用的內存空間會差不多是恒定的數值,每次新創建出來的bitmap都會需要占用一塊單獨的內存區域,如下圖所示:

這里寫圖片描述

為了解決上圖所示的效率問題,Android在解碼圖片的時候引進了inBitmap屬性,使用這個屬性可以得到下圖所示的效果:

這里寫圖片描述

使用inBitmap屬性可以告知Bitmap解碼器去嘗試使用已經存在的內存區域,新解碼的bitmap會嘗試去使用之前那張bitmap在heap中所占據的pixel data內存區域,而不是去問內存重新申請一塊區域來存放bitmap。利用這種特性,即使是上千張的圖片,也只會僅僅只需要占用屏幕所能夠顯示的圖片數量的內存大小。下面是如何使用inBitmap的代碼示例:

這里寫圖片描述

使用inBitmap需要注意幾個限制條件:

在SDK 11 -> 18之間,重用的bitmap大小必須是一致的,例如給inBitmap賦值的圖片大小為100-100,那么新申請的bitmap必須也為100-100才能夠被重用。從SDK 19開始,新申請的bitmap大小必須小于或者等于已經賦值過的bitmap大小。 新申請的bitmap與舊的bitmap必須有相同的解碼格式,例如大家都是8888的,如果前面的bitmap是8888,那么就不能支持4444與565格式的bitmap了。 我們可以創建一個包含多種典型可重用bitmap的對象池,這樣后續的bitmap創建都能夠找到合適的“模板”去進行重用。如下圖所示:

這里寫圖片描述

Google介紹了一個開源的加載bitmap的庫:Glide,這里面包含了各種對bitmap的優化技巧。

18、The Performance Lifecycle

大多數開發者在沒有發現嚴重性能問題之前是不會特別花精力去關注性能優化的,通常大家關注的都是功能是否實現。當性能問題真的出現的時候,請不要慌亂。我們通常采用下面三個步驟來解決性能問題。

Gather:收集數據

我們可以通過Android SDK里面提供的諸多工具來收集CPU,GPU,內存,電量等等性能數據,

Insight:分析數據

通過上面的步驟,我們獲取到了大量的數據,下一步就是分析這些數據。工具幫我們生成了很多可讀性強的表格,我們需要事先了解如何查看表格的數據,每一項代表的含義,這樣才能夠快速定位問題。如果分析數據之后還是沒有找到問題,那么就只能不停的重新收集數據,再進行分析,如此循環。

Action:解決問題

定位到問題之后,我們需要采取行動來解決問題。解決問題之前一定要先有個計劃,評估這個解決方案是否可行,是否能夠及時的解決問題。

19、Tools not Rules

雖然前面介紹了很多調試的方法,處理技巧,規范建議等等,可是這并不意味著所有的情況都適用,我們還是需要根據當時的情景做特定靈活的處理。

20、Memory Profiling 101

圍繞Android生態系統,不僅僅有Phone,還有Wear,TV,Auto等等。對這些不同形態的程序進行性能優化,都離不開內存調試這個步驟。見第一季內容。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 万源市| 寿宁县| 龙江县| 绥宁县| 西青区| 克东县| 屯昌县| 高淳县| 屏山县| 阳信县| 武宁县| 衡东县| 上思县| 武冈市| 贵溪市| 铁力市| 马鞍山市| 洛川县| 武清区| 海阳市| 柳江县| 逊克县| 鸡泽县| 松溪县| 理塘县| 松原市| 榆中县| 孟津县| 元谋县| 辽阳市| 西藏| 淮南市| 宁海县| 敖汉旗| 达尔| 玉溪市| 托克托县| 乌什县| 阳泉市| 山东省| 调兵山市|