一金抡、冷熱啟動(dòng)概念:
1匀钧、冷啟動(dòng):冷啟動(dòng)因?yàn)橄到y(tǒng)會(huì)重新創(chuàng)建一個(gè)新的進(jìn)程分配給它序仙,所以會(huì)先創(chuàng)建和初始化Application類,再創(chuàng)建和初始化MainActivity類(包括一系列的測(cè)量裆甩、布局冗锁、繪制),最后顯示在界面上嗤栓。
2冻河、熱啟動(dòng):熱啟動(dòng)因?yàn)闀?huì)從已有的進(jìn)程中來啟動(dòng),所以熱啟動(dòng)就不會(huì)走Application這步了,而是直接走M(jìn)ainActivity(包括一系列的測(cè)量芋绸、布局媒殉、繪制),所以熱啟動(dòng)的過程只需要?jiǎng)?chuàng)建和初始化一個(gè)MainActivity就行了摔敛,而不必創(chuàng)建和初始化Application廷蓉,因?yàn)橐粋€(gè)應(yīng)用從新進(jìn)程的創(chuàng)建到進(jìn)程的銷毀,Application只會(huì)初始化一次马昙。
二桃犬、冷啟動(dòng)流程:
應(yīng)用的第一次啟動(dòng)才算完成,這時(shí)候我們看到的界面也就是所說的第一幀行楞。所以攒暇,總結(jié)一下,應(yīng)用的啟動(dòng)流程如下:
Application的創(chuàng)建和初始化——>attachBaseContext()——>onCreate()——>Activity的構(gòu)造方法——>onCreate()——>配置主題中背景等屬性——>onStart()——>onResume()——>contentView的measure/layout/draw顯示在界面上子房。
三形用、工具和分析方法:
1、測(cè)量activity的啟動(dòng)時(shí)間-------Activity的reportFullyDrawn()方法
2证杭、adb shell screenrecord --bugreport /sdcard/launch.mp4 錄制屏幕
優(yōu)化方法:
1田度、不要讓Application參與業(yè)務(wù)的操作
2、不要在APPlication進(jìn)行耗時(shí)操作解愤,比如有些開發(fā)者會(huì)在自己的APP里一系列文件夾或文件(比如我自己)镇饺,這些I/O操作應(yīng)該放到"確實(shí)該使用的時(shí)候再去創(chuàng)建"亦或者是數(shù)據(jù)庫的一些操作。
3送讲、不要以靜態(tài)變量的方式在Application中保存數(shù)據(jù)等奸笤。
java代碼優(yōu)化
1、緩存:需要頻繁訪問哼鬓,或者訪問一次開銷比較大的:
需要重復(fù)用到的监右,可以緩存下來,比如res.getstring()這種
其他緩存:圖片緩存魄宏、線程池秸侣、消息緩存handler.obtainMessage()存筏、
2宠互、數(shù)據(jù)結(jié)構(gòu)的選擇:
Android也提供了一些性能更優(yōu)的數(shù)據(jù)類型,如SparseArray椭坚、SparseBooleanArray予跌、SparseIntArray、Pair善茎。
Sparse系列的數(shù)據(jù)結(jié)構(gòu)是為key為int情況的特殊處理券册,采用二分查找及簡單的數(shù)組存儲(chǔ),加上不需要泛型轉(zhuǎn)換的開銷,相對(duì)Map來說性能更優(yōu)烁焙。
3航邢、算法的選擇:
盡量不用o(n*2)的算法;有必要的時(shí)間以空間換時(shí)間
4骄蝇、異步:
耗時(shí)操作放到異步線程里面去執(zhí)行
5膳殷、提前或延遲操作,錯(cuò)開時(shí)間段提高TPS
(1) 延遲操作:不在Activity九火、Service赚窃、BroadcastReceiver的生命周期等對(duì)響應(yīng)時(shí)間敏感函數(shù)中執(zhí)行耗時(shí)操作,可適當(dāng)delay岔激。Android中可以采取handler.postDelayed勒极,handler.postAtTime,handler.sendMessageDelayed虑鼎,View.postDelayed辱匿,AlarmManager定時(shí)等。
布局優(yōu)化:
工具:hierarchy viewer炫彩、lint
策略:減少布局的復(fù)雜性掀鹅,布局深度
方法:
1、include
2媒楼、merge
3翠订、viewstub默認(rèn)不會(huì)顯示,需要的時(shí)候再inflate霞丧; gone
4掖桦、listview的優(yōu)化:復(fù)用convertview, viewHolder來減少findviewById, 局部更新
5、用SurfaceView或TextureView代替普通View:
他們可以通過將繪圖操作移動(dòng)到另一個(gè)單獨(dú)線程上提高性能夺颤;因?yàn)镾urfaceView在常規(guī)視圖系統(tǒng)之外痢缎,所以無法像常規(guī)試圖一樣移動(dòng)、縮放或旋轉(zhuǎn)一個(gè)SurfaceView世澜。TextureView是Android4.0引入的独旷,除了與SurfaceView一樣在單獨(dú)線程繪制外,還可以像常規(guī)視圖一樣被改變寥裂。
6嵌洼、盡量為所有分辨率創(chuàng)建資源,減少不必要的硬件縮放封恰,這會(huì)降低UI的繪制速度
數(shù)據(jù)庫優(yōu)化
1麻养、索引:
CREATE INDEX mycolumn_index ON mytable (myclumn)
好處:索引可以大大查詢的速度;包括對(duì)表查詢诺舔、連表查詢鳖昌、分組查詢备畦、排序查詢
壞處:增刪改需要維護(hù)索引,影響性能许昨;而且索引需要占用一定的物理空間
適用場(chǎng)景:更新頻率較低懂盐,查詢頻率較高,經(jīng)常有范圍查詢(>, <, =, >=, <=)或order by糕档、group by發(fā)生時(shí)的字段建議使用索引允粤;經(jīng)常同時(shí)存取多列,且每列都含有重復(fù)值可考慮建立復(fù)合索引
2翼岁、事務(wù):
Sqlite默認(rèn)會(huì)為每個(gè)插入类垫、更新操作創(chuàng)建一個(gè)事務(wù),并且在每次插入琅坡、更新后立即提交(創(chuàng)建事務(wù)->執(zhí)行語句->提交)悉患;優(yōu)化的方式是,批量操作時(shí)榆俺,創(chuàng)建事務(wù)->執(zhí)行n條語句->提交
public void insertWithOneTransaction() {
SQLiteDatabase db = sqliteOpenHelper.getWritableDatabase();
// Begins a transaction
db.beginTransaction();
try {
// your sqls
for (int i = 0; i < 100; i++) {
db.insert(yourTableName, null, value);
}
// marks the current transaction as successful
db.setTransactionSuccessful();
} catch (Exception e) {
// process it
e.printStackTrace();
} finally {
// end a transaction
db.endTransaction();
}
}
3售躁、數(shù)據(jù)庫查詢操作放到異步線程里面去做
4、語句的拼接使用StringBuilder代替String
這個(gè)就不多說了茴晋,簡單的string相加會(huì)導(dǎo)致創(chuàng)建多個(gè)臨時(shí)對(duì)象消耗性能陪捷。StringBuilder的空間預(yù)分配性能好得多。如果你對(duì)字符串的長度有大致了解诺擅,如100字符左右市袖,可以直接new StringBuilder(128)指定初始大小,減少空間不夠時(shí)的再次分配烁涌。
5苍碟、查詢時(shí)返回更少的結(jié)果集及更少的字段。
查詢時(shí)只取需要的字段和結(jié)果集撮执,更多的結(jié)果集會(huì)消耗更多的時(shí)間及內(nèi)存微峰,更多的字段會(huì)導(dǎo)致更多的內(nèi)存消耗。
6抒钱、少用cursor.getColumnIndex蜓肆,用static變量記住某一列的index
根據(jù)性能調(diào)優(yōu)過程中的觀察cursor.getColumnIndex的時(shí)間消耗跟cursor.getInt相差無幾∧北遥可以在建表的時(shí)候用static變量記住某列的index仗扬,直接調(diào)用相應(yīng)index而不是每次查詢。
其他:
視覺體驗(yàn)上的“快”:
為啟動(dòng)的Activity自定義一個(gè)Theme瑞信,Theme里的windowBackground設(shè)置成我們想要讓用戶看到的畫面厉颤;
為啟動(dòng)的Activity自定義一個(gè)Theme
<style name="AppTheme.Launcher">
<item name="android:windowBackground">@drawable/window_background_statusbar_toolbar_tab</item>
</style>
將新的Theme應(yīng)用到設(shè)置到AndroidManifest.xml中
<activity
android:name=".MainActivity"
android:theme="@style/AppTheme.Launcher">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
由于給MainActivity設(shè)置了一個(gè)新的Theme,這樣做會(huì)覆蓋原來的Theme凡简,所以在MainActivity中需要設(shè)置回原來的Theme