Android性能優化(面試必備)

熱文導讀 | 點擊標題閱讀

[推薦]Android Studio下對資源進行分包,很實用

吊炸天!74款APP完整源碼!

Android 高仿懂球帝我是教練效果


公衆號:Java和Android架構

關注回覆:Android,iOS,PHP,js,HTML5,Python,機器學習 ,AI,大數據Hadoop,c++,J2EE等關鍵字就能免費獲取學習資料視頻


前幾篇文章詳細討論了Android中性能優化的問題。本篇文章是對前面部分的一個總結(讀者可以翻看之前的文章),同時筆者結合了實際項目中的經驗,希望能對大家拋磚引玉。

Android性能優化,也是面試中幾乎必問的知識點。本文也將告訴你如何回答這樣的問題。

實際項目中的Android性能優化主要有如下幾個方面:

  • 編寫高效代碼—開發中總結出的一些小的性能Tips

  • Layout佈局優化

  • 內存優化

編寫高效代碼

本節告訴你如何編寫高效代碼,並總結了一些小的性能優化點。

編寫高效代碼的兩個原則

  • 不要寫不需要的代碼

  • 不要分配不必要的內存

以上兩個原則,似乎感覺是廢話,但確實是編程的最高境界,也是我們編寫代碼的過程中時刻需要思考和注意的兩個方面。

那麼如何做到如上兩點呢?下面列出了一些實際開發中的小的例子。

1.避免產生不必要的對象

例如:

  • int的數組比Integer對象數組要好得多。兩個平行的int數組要比一個(int,int)型的對象數組高效。這對於其他任何基本數據類型的組合都通用

  • 兩個平行數組Foo[],Bar[]會優於一個(Foo,Bar)對象的數組

  • 通常來講,儘量避免創建短時零時對象.少的對象創建意味着低頻的垃圾回收

對象的分配和回收都是需要代價的;分配的內存越多,就會引起強制的內存回收;給用戶體驗增加小的停頓間隙,從而影響用戶體驗。

用戶能感覺到卡頓的時間延遲是100ms ~ 200ms

2.用靜態代替虛擬

  • 如果方法不需要訪問某對像的字段,將該方法設置爲靜態,調用速度會提升15%~20%

  • 對於常量使用 final static

final static int intVal = 42;         
final static String strVal = "Hello world";


注:這種優化僅僅是針對基本數據類型和String類型常量的,而非任意的引用類型。但儘可能的將常量聲明爲static final是一種好的做法。

爲什麼儘量將將常量聲明爲static final是一種好的做法呢?這是因爲:

  1. 當上面的代碼塊沒有final修飾符時,編譯器會生成一個類初始化方法,當該類初次被使用時執行,這個方法將42存入intVal中,並得到類文件字符串常量strVal的一個引用。當這些值在後面被引用時,他們通過字段查找進行訪問。

  2. 聲明爲final字段後, 類不再需要方法,因爲常量通過靜態字段初始化器載進入dex文件中。引用intVal的代碼,將直接調用整型值42;而訪問strVal,也會採用相對開銷較小的“字符串常量”指令替代字段查找。

本節討論的是一些微小的性能提升,可能不會給你的程序性能改善產生顯著的效果。決定程序整體性能的仍然取決於程序的業務邏輯設計、代碼的數據結構和算法。但你需要將這些優化技巧應用到平時的編碼過程中,積少成多,也會對性能有很大的影響

3.避免內部的getter和setter

4.使用增強for循環

對於ArrayList和數組,手寫的計數循環迭代要比增強for循環快3倍

結論:優先採用改進for循環,但在性能要求苛刻的ArrayList迭代中,考慮採用手寫計數循環。 (參見 Effective Java item 46.)

5.避免使用浮點數

通常的經驗是,在Android設備中,浮點數會比整型慢兩倍

6.在沒有JIT的設備上,調用方法所傳遞的對象採用具體的類型而非接口類型會更高效

void methodA(List<String> list);

void methodA(ArrayList<String> list);

如上,後一種比前一種更高效。

7.數據庫操作方法的優化

  • 儘量利用原生的SQL語句

    原生的SQL省去了拼接sql語句的步驟,要比SqliteDatabase提供的insert、query、 update、delete等函數效率高。當數據庫越大,差別也越大

  • 當操作條數較多時,利用事務進行批處理

    這樣SQLite將把全部要執行的SQL語句先緩存在內存當中,然後等到COMMIT的時候一次性的寫入數據庫,這樣數據庫文件只被打開關閉了一次,效率自然大大的提高

db.beginTransaction();        
for(Collection c:colls){    insert(db, c); } db.setTransactionSuccessful();

8.Http請求方式的選擇

Android 內置了兩種HTTP方式:HttpURLConnection 和 Apache HttpClient。這兩種都支持HTTPS、流式上傳和下載、可配置超時、IPv6和連接池。在Gingerbread或者更高版本時,推薦使用HttpURLConnection。

這是因爲: HttpURLConnection API 更簡單,包更小。同時對傳輸數據的壓縮和響應的緩存處理減少了網絡帶寬、提高了速度,也節省了電量。

優化佈局

Layouts是Android應用裏直接影響用戶體驗的一個關鍵部分。如果Layout設計的不好,可能導致你的應用大量的內存佔用從而導致UI響應很慢。Android SDK提供了工具幫助你分析你的Layouts的性能問題。結合工具同時遵循本節討論的做法,能實現滑動流暢、佔用內存最小的用戶界面。

使用Hierarchy Viewer

Hierarchy Viewer工具位於 < SDK >\tools\目錄下 ,該工具能分析出你的佈局不合理和可以優化的地方。具體用法參見之前文章的介紹例子。

大多數情況下,佈局渲染時間差別較大的原因是在LinaerLayout裏使用了layout_weight。這將會增加測量(Measure)的時間。你應該仔細的考慮是否有必要使用layout weight。

使用Lint

使用Lint — 查看你的view 層級哪些地方可以優化

  1. 使用compound drawables - 一個包含了ImageView與TextView的LinearLayout可以被當作一個compound drawable來處理

  2. 使用merge根框架 - 如果FramLayout僅僅是一個純粹的(沒有設置背景,間距等)佈局根元素,我們可以使用merge標籤來當作根標籤

  3. 無用的分支 - 如果一個layout並沒有任何子組件,那麼可以被移除,這樣可以提高效率

  4. 無用的父控件 - 如果一個layout只有子控件,沒有兄弟控件,並且不是一個ScrollView或者根節點,而且沒有設置背景,那麼我們可以移除這個父控件,直接把子控件提升爲父控件

  5. 深層次的layout - 儘量減少內嵌的層級,考慮使用更多平級的組件 RelativeLayout or GridLayout來提升佈局性能,默認最大的深度是10

其他一些佈局要點

  1. Re-using Layouts with <include/>

  2. Use the <merge>

  3. Loading Views on Demand

<ViewStub      
      android:id="@+id/stub_import"     android:inflatedId="@+id/panel_import"                     
      android:layout="@layout/progress_overlay ….  />

優化App內存

爲了垃圾回收器能回收你係統的內存,你應該避免引起內存泄露(通常由全局成員hold了對象引用),而且要在合適的時間點(如生命週期回調時,這將在後面章節進一步討論)釋放被引用的對象。

慎用Service

  1. Service執行完後臺任務後要停止,注意:不要service任務已完成,而不去停止service

  2. 使用IntentService

    IntentService不同於普通的Service之處是:

    • 提交的task系統會post到子線程運行

    • 當後臺運行的task完成時,系統會stop掉IntentService

onHandleIntent(Intent intent)

當一個service不需要而還在後臺運行時,這是最消耗內存的內存管理錯誤。因此要慎用服務,當服務完成後臺任務時要記得關閉。如果不這樣做,由於RAM的限制,你的app運行將變得非常卡,用戶也將發現app錯誤的行爲,最後卸載你的應用

Release memory when your user interface becomes hidden

例如,在該onStop()裏做釋放資源(例如網絡連接、註銷廣播等)的工作

使用優化後的集合容器

例如:SparseArray、SparseBooleanArray、LongSpareArray …..

儘量避免使用枚舉

相比於靜態常量,枚舉會有超過其兩倍以上的內存開銷,在android中需嚴格避免使用枚舉

避免使用依賴注入框架

使用ProGuard消除沒有使用的代碼

使用zipalign優化和對齊你的apk

  1. 優化避免使用更多的內存、資源不會再從apk中映射入內存。

注:google play store不接受沒有進行zipalign的apk

使用MAT分析和優化內存

  1. I/O使用後需要關閉,數據庫和Cursor等使用後要關閉

  2. 使用finalize()+MAT 分析內存泄露

Android優化主要就是內存、佈局和性能的優化,本文概況和總結了Android中優化的一些知識點。其實,裏面的很多的知識點都可以展開進行講解。如果大家對裏面某個方面感興趣,可以給我們留言。後續的文章我們會進行專門的討論。



Java和Android架構

歡迎關注我們,一起討論技術,掃描和長按下方的二維碼可快速關注我們。搜索微信公衆號:JANiubility。

公衆號:JANiubility


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章