一般咱們寫程序,都是在項目計劃的壓力下完成的,此時完成的代碼能夠完成具體業務邏輯,可是性能不必定是最優化的。通常來講,優秀的程序員在寫完代碼以後都會不斷的對代碼進行重構。重構的好處有不少,其中一點,就是對代碼進行優化,提升軟件的性能。下面咱們就從幾個方面來了解Android開發過程當中的代碼優化。程序員
1)靜態變量引發內存泄露算法
在代碼優化的過程當中,咱們須要對代碼中的靜態變量特別留意。靜態變量是類相關的變量,它的生命週期是從這個類被聲明,到這個類完全被垃圾回收器回收纔會被銷燬。因此,通常狀況下,靜態變量從所在的類被使用開始就要一直佔用着內存空間,直到程序退出。若是不注意,靜態變量引用了佔用大量內存的資源,形成垃圾回收器沒法對內存進行回收,就可能形成內存的浪費。緩存
先來看一段代碼,這段代碼定義了一個Activity。安全
這段代碼中有一個靜態的Resources對象。代碼片斷mResources = this.getResources()對Resources對象進行了初始化。這時Resources對象擁有了當前Activity對象的引用,Activity又引用了整個頁面中全部的對象。ide
若是當前的Activity被從新建立(好比橫豎屏切換,默認狀況下整個Activity會被從新建立),因爲Resources引用了第一次建立的Activity,就會致使第一次建立的Activity不能被垃圾回收器回收,從而致使第一次建立的Activity中的全部對象都不能被回收。這個時候,一部份內存就浪費掉了。性能
經驗分享:優化 在實際項目中,咱們常常會把一些對象的引用加入到集合中,若是這個集合是靜態的話,就須要特別注意了。當不須要某對象時,務必及時把它的引用從集合中清理掉。或者能夠爲集合提供一種更新策略,及時更新整個集合,這樣能夠保證集合的大小不超過某值,避免內存空間的浪費。this |
2)使用Application的Contextspa
在Android中,Application Context的生命週期和應用的生命週期同樣長,而不是取決於某個Activity的生命週期。若是想保持一個長期生命的對象,而且這個對象須要一個Context,就可使用Application對象。能夠經過調用Context.getApplicationContext()方法或者Activity.getApplication()方法來得到Application對象。線程
依然拿上面的代碼做爲例子。能夠將代碼修改爲下面的樣子。
在這裏將this.getResources()修改成this.getApplication().getResources()。修改之後,Resources對象擁有的是Application對象的引用。若是Activity被從新建立,第一次建立的Activity就能夠被回收了。
3)及時關閉資源
Cursor是Android查詢數據後獲得的一個管理數據集合的類。正常狀況下,若是咱們沒有關閉它,系統會在回收它時進行關閉,可是這樣的效率特別低。若是查詢獲得的數據量較小時還好,若是Cursor的數據量很是大,特別是若是裏面有Blob信息時,就可能出現內存問題。因此必定要及時關閉Cursor。
下面給出一個通用的使用Cursor的代碼片斷。
即對異常進行捕獲,而且在finally中將cursor關閉。
一樣的,在使用文件的時候,也要及時關閉。
4)使用Bitmap及時調用recycle()
前面的章節講過,在不使用Bitmap對象時,須要調用recycle()釋放內存,而後將它設置爲null。雖然調用recycle()並不能保證當即釋放佔用的內存,可是能夠加速Bitmap的內存的釋放。
在代碼優化的過程當中,若是發現某個Activity用到了Bitmap對象,卻沒有顯式的調用recycle()釋放內存,則須要分析代碼邏輯,增長相關代碼,在再也不使用Bitmap之後調用recycle()釋放內存。
5)對Adapter進行優化
下面以構造ListView的BaseAdapter爲例說明如何對Adapter進行優化。
在BaseAdapter類中提供了以下方法:
當ListView列表裏的每一項顯示時,都會調用Adapter的getView方法返回一個View,
來向ListView提供所須要的View對象。
下面是一個完整的getView()方法的代碼示例。
當向上滾動ListView時,getView()方法會被反覆調用。getView()的第二個參數convertView是被緩存起來的List條目中的View對象。當ListView滑動的時候,getView可能會直接返回舊的convertView。這裏使用了convertView和ViewHolder,能夠充分利用緩存,避免反覆建立View對象和TextView對象。
若是ListView的條目只有幾個,這種技巧並不能帶來多少性能的提高。可是若是條目有幾百甚至幾千個,使用這種技巧只會建立幾個convertView和ViewHolder(取決於當前界面可以顯示的條目數),性能的差異就很是很是大了。
6)代碼「微優化」
當今時代已經進入了「微時代」。這裏的「微優化」指的是代碼層面的細節優化,即不改動代碼總體結構,不改變程序原有的邏輯。儘管Android使用的是Dalvik虛擬機,可是傳統的Java方面的代碼優化技巧在Android開發中也都是適用的。
下面簡要列舉一部分。由於通常Java開發者都可以理解,就再也不作具體的代碼說明。
建立新的對象都須要額外的內存空間,要儘可能減小建立新的對象。
將類、變量、方法等等的可見性修改成最小。
針對字符串的拼接,使用StringBuffer替代String。
不要在循環當中聲明臨時變量,不要在循環中捕獲異常。
若是對於線程安全沒有要求,儘可能使用線程不安全的集合對象。
使用集合對象,若是事先知道其大小,則能夠在構造方法中設置初始大小。
文件讀取操做須要使用緩存類,及時關閉文件。
慎用異常,使用異常會致使性能下降。
若是程序會頻繁建立線程,則能夠考慮使用線程池。
經驗分享: 代碼的微優化有不少不少東西能夠講,小到一個變量的聲明,大到一段算法。尤爲在代碼Review的過程當中,可能會反覆審查代碼是否能夠優化。不過我認爲,代碼的微優化是很是耗費時間的,沒有必要從頭至尾將全部代碼都優化一遍。開發者應該根據具體的業務邏輯去專門針對某部分代碼作優化。好比應用中可能有一些方法會被反覆調用,那麼這部分代碼就值得專門作優化。其它的代碼,須要開發者在寫代碼過程當中去注意。 |