熱文導讀 | 點擊標題閱讀
[推薦]Android
Studio下對資源進行分包,很實用
關注回覆: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是一種好的做法呢?這是因爲:
-
當上面的代碼塊沒有final修飾符時,編譯器會生成一個類初始化方法,當該類初次被使用時執行,這個方法將42存入intVal中,並得到類文件字符串常量strVal的一個引用。當這些值在後面被引用時,他們通過字段查找進行訪問。
-
聲明爲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 層級哪些地方可以優化
-
使用compound drawables - 一個包含了ImageView與TextView的LinearLayout可以被當作一個compound drawable來處理
-
使用merge根框架 - 如果FramLayout僅僅是一個純粹的(沒有設置背景,間距等)佈局根元素,我們可以使用merge標籤來當作根標籤
-
無用的分支 - 如果一個layout並沒有任何子組件,那麼可以被移除,這樣可以提高效率
-
無用的父控件 - 如果一個layout只有子控件,沒有兄弟控件,並且不是一個ScrollView或者根節點,而且沒有設置背景,那麼我們可以移除這個父控件,直接把子控件提升爲父控件
-
深層次的layout - 儘量減少內嵌的層級,考慮使用更多平級的組件 RelativeLayout or GridLayout來提升佈局性能,默認最大的深度是10
其他一些佈局要點
-
Re-using Layouts with <include/>
-
Use the <merge>
-
Loading Views on Demand
<ViewStub
android:id="@+id/stub_import"
android:inflatedId="@+id/panel_import"
android:layout="@layout/progress_overlay ….
/>
優化App內存
爲了垃圾回收器能回收你係統的內存,你應該避免引起內存泄露(通常由全局成員hold了對象引用),而且要在合適的時間點(如生命週期回調時,這將在後面章節進一步討論)釋放被引用的對象。
慎用Service
-
Service執行完後臺任務後要停止,注意:不要service任務已完成,而不去停止service
-
使用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
-
優化避免使用更多的內存、資源不會再從apk中映射入內存。
注:google play store不接受沒有進行zipalign的apk
使用MAT分析和優化內存
-
I/O使用後需要關閉,數據庫和Cursor等使用後要關閉
-
使用finalize()+MAT 分析內存泄露
Android優化主要就是內存、佈局和性能的優化,本文概況和總結了Android中優化的一些知識點。其實,裏面的很多的知識點都可以展開進行講解。如果大家對裏面某個方面感興趣,可以給我們留言。後續的文章我們會進行專門的討論。
Java和Android架構
歡迎關注我們,一起討論技術,掃描和長按下方的二維碼可快速關注我們。或搜索微信公衆號:JANiubility。
公衆號:JANiubility