- 使用更加輕量的數(shù)據(jù)結(jié)構(gòu)
考慮使用Android專門的ArrayMap/SparseArray而不是HashMap等傳統(tǒng)數(shù)據(jù)結(jié)構(gòu),SparseArray更加高效在于他們避免了對key與value的autobox自動裝箱笋粟,并且避免了裝箱后的解箱寞宫。 - 避免在Android里面使用Enum壕鹉,使用enum比靜態(tài)int省的dex大一倍蛉腌。使用@Intdef
- 避免View的泄露導(dǎo)致Activity的泄露,2.3的Drawable4.0修復(fù)
- 復(fù)雜繪制開啟硬件加速窘游,SDK16開始屬性動畫可以直接開啟:ViewPropertyAnimator.alpha().withLayer()
- bitmap優(yōu)化1.解碼格式ARGB_8888/RGB_565;2.縮放指定大小inScaled况芒,inDensity惜纸,inTargetDensity;3.inbitmap牛柒;4.bitmappool
- 開啟嚴(yán)格模式 Strict Mode堪簿,預(yù)防ANR
7.自定義View1.ClipRect裁剪畫布,2.Canvas.quickReject查找交叉區(qū)域 - AlarmManager皮壁、JobSchedulor定時(shí)任務(wù)
9.發(fā)隱式Intent之前調(diào)用resolveActivity做檢查
10.提供了NotificationCompat兼容類來幫助開發(fā)實(shí)現(xiàn)體驗(yàn)統(tǒng)一的Notification參考
11.使用MediaSessionCompat操作音樂的播放
限制應(yīng)用的內(nèi)存
為了整個Android系統(tǒng)的內(nèi)存控制需要椭更,Android系統(tǒng)為每一個應(yīng)用程序都設(shè)置了一個硬性的Dalvik Heap Size最大限制閾值,這個閾值在不同的設(shè)備上會因?yàn)镽AM大小不同而各有差異蛾魄。如果你的應(yīng)用占用內(nèi)存空間已經(jīng)接近這個閾值虑瀑,此時(shí)再嘗試分配內(nèi)存的話,很容易引起OutOfMemoryError
的錯誤滴须。
ActivityManager.getMemoryClass()
可以用來查詢當(dāng)前應(yīng)用的Heap Size閾值舌狗,這個方法會返回一個整數(shù),表明你的應(yīng)用的Heap Size閾值是多少M(fèi)b(megabates)扔水。
硬件加速
嚴(yán)格模式Strict Mode
UI線程被阻塞超過5秒痛侍,就會出現(xiàn)ANR,這太糟糕了魔市。防止程序出現(xiàn)ANR是很重要的事情主届,那么如何找出程序里面潛在的坑,預(yù)防ANR呢待德?很多大部分情況下執(zhí)行很快的方法君丁,但是他們有可能存在巨大的隱患,這些隱患的爆發(fā)就很容易導(dǎo)致ANR将宪。
Android提供了一個叫做Strict Mode的工具绘闷,我們可以通過手機(jī)設(shè)置里面的開發(fā)者選項(xiàng),打開Strict Mode選項(xiàng)较坛,如果程序存在潛在的隱患印蔗,屏幕就會閃現(xiàn)紅色。我們也可以通過StrictMode API在代碼層面做細(xì)化的跟蹤丑勤,可以設(shè)置StrictMode監(jiān)聽那些潛在問題喻鳄,出現(xiàn)問題時(shí)如何提醒開發(fā)者,可以對屏幕閃紅色确封,也可以輸出錯誤日志除呵。下面是官方的代碼示例:
public void onCreate() {
if (DEVELOPER_MODE) {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork() // or .detectAll() for all detectable problems
.penaltyLog()
.build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()
.detectLeakedClosableObjects()
.penaltyLog()
.penaltyDeath()
.build());
}
super.onCreate();
}
自定義View
Android系統(tǒng)有提供超過70多種標(biāo)準(zhǔn)的View,例如TextView爪喘,ImageView颜曾,Button等等。在某些時(shí)候秉剑,這些標(biāo)準(zhǔn)的View無法滿足我們的需要泛豪,那么就需要我們自己來實(shí)現(xiàn)一個View,這節(jié)會介紹如何優(yōu)化自定義View的性能侦鹏。
通常來說诡曙,針對自定義View,我們可能犯下面三個錯誤:
- 我們知道調(diào)用View.invalidate()會觸發(fā)View的重繪略水,有兩個原則需要遵守价卤,第1個是僅僅在View的內(nèi)容發(fā)生改變的時(shí)候才去觸發(fā)invalidate方法,第2個是盡量使用ClipRect等方法來提高繪制的性能渊涝。
- 減少繪制時(shí)不必要的繪制元素慎璧,對于那些不可見的元素,我們需要盡量避免重繪跨释。
- 對于不在屏幕上的元素胸私,可以使用Canvas.quickReject把他們給剔除,避免浪費(fèi)CPU資源鳖谈。另外盡量使用GPU來進(jìn)行UI的渲染岁疼,這樣能夠極大的提高程序的整體表現(xiàn)性能。
最后請時(shí)刻牢記缆娃,盡量提高View的繪制性能捷绒,這樣才能保證界面的刷新幀率盡量的高。更多關(guān)于這部分的內(nèi)容龄恋,可以看這里
Bitmap圖片相關(guān)
1.解碼格式
所以為了避免加載一張超大的圖片疙驾,需要盡量減少這張圖片所占用的內(nèi)存大小,Android為圖片提供了4種解碼格式郭毕,他們分別占用的內(nèi)存大小如下圖所示:
隨著解碼占用內(nèi)存大小的降低它碎,清晰度也會有損失。我們需要針對不同的應(yīng)用場景做不同的處理显押,大圖和小圖可以采用不同的解碼率扳肛。在Android里面可以通過下面的代碼來設(shè)置解碼率:
2.圖片縮放:
對bitmap做縮放,這也是Android里面最遇到的問題乘碑。對bitmap做縮放的意義很明顯挖息,提示顯示性能,避免分配不必要的內(nèi)存兽肤。Android提供了現(xiàn)成的bitmap縮放的API套腹,叫做createScaledBitmap()绪抛,使用這個方法可以獲取到一張經(jīng)過縮放的圖片。
上面的方法能夠快速的得到一張經(jīng)過縮放的圖片电禀,可是這個方法能夠執(zhí)行的前提是幢码,原圖片需要事先加載到內(nèi)存中,如果原圖片過大尖飞,很可能導(dǎo)致OOM症副。下面介紹其他幾種縮放圖片的方式。
inSampleSize能夠等比的縮放顯示圖片政基,同時(shí)還避免了需要先把原圖加載進(jìn)內(nèi)存的缺點(diǎn)贞铣。我們會使用類似像下面一樣的方法來縮放bitmap:
重要另外,我們還可以使用inScaled沮明,inDensity辕坝,inTargetDensity
的屬性來對解碼圖片做處理,源碼如下圖所示:
還有一個經(jīng)常使用到的技巧是inJustDecodeBounds珊擂,使用這個屬性去嘗試解碼圖片圣勒,可以事先獲取到圖片的大小而不至于占用什么內(nèi)存。如下圖所示:
隱式Intent之前調(diào)用resolveActivity做檢查參考
Intent intent = new Intent(Intent.ACTION_XXX);
ComponentName componentName = intent.resolveActivity(getPackageManager());
if(componentName != null) {
String className = componentName.getClassName();
}
Notification兼容性問
為了解決Android系統(tǒng)版本差異導(dǎo)致的Notification兼容性問題摧扇,Android官方提供了NotificationCompat兼容類來幫助開發(fā)實(shí)現(xiàn)體驗(yàn)統(tǒng)一的Notification圣贸。通常來說,建立一個Notification至少會有三種元素:圖標(biāo)扛稽,標(biāo)題吁峻,文本。我們通常會使用如下的代碼來實(shí)現(xiàn)一個基礎(chǔ)的Notification功能: