1:自定義View
? ? ? 1)耗時(shí)邏輯不能寫(xiě)在onDraw()中。因?yàn)閁I的繪制幀率為每秒60次,也就是說(shuō)每幀的繪制時(shí)間是16毫秒简逮,如果在16毫秒內(nèi)未能完成一幀的繪制,就會(huì)造成丟幀强缘,引起卡頓。
? ? ? ?2)onDraw()中不要定義局部對(duì)象不傅,這是因?yàn)閛nDraw()很可能被頻繁調(diào)用欺旧,這樣短時(shí)間內(nèi)會(huì)產(chǎn)生大量臨時(shí)對(duì)象,這樣不僅會(huì)占用過(guò)多內(nèi)存還會(huì)導(dǎo)致頻繁的GC蛤签,降低程序的執(zhí)行效率
2:過(guò)度繪制辞友。
? ? 1)減少view層級(jí),使用ConstraintLayout震肮,ViewStub称龙,include,merge標(biāo)簽
? ? 2)使用android studio的Layout Inspector工具(替代Hierarchy Viewer)檢查視圖結(jié)構(gòu)
3:耗時(shí)操作戳晌,例如I/O操作鲫尊、數(shù)據(jù)庫(kù)耗時(shí)操作在UI線程中執(zhí)行,針對(duì)I/O耗時(shí)操作沦偎,可以放到異步任務(wù)或者線程池執(zhí)行疫向;數(shù)據(jù)庫(kù)可以創(chuàng)建中間層,利用緩存處理豪嚎,或者多線程處理
4:內(nèi)存抖動(dòng)搔驼,頻繁GC,造成大量對(duì)象的創(chuàng)建和回收侈询,導(dǎo)致堆內(nèi)存碎片化嚴(yán)重舌涨,在分配大內(nèi)存對(duì)象時(shí)容易發(fā)生內(nèi)存泄漏,避免手動(dòng)System.gc().雖 然 有 停 止 復(fù) 制 回 收 算 法 會(huì) 整 理 堆 內(nèi) 存 扔字,但是此算法需要消耗很大的內(nèi)存和時(shí)間
? 案例:因?yàn)榇騆og而進(jìn)行了字符串拼接囊嘉,一旦這個(gè)函數(shù)被比較頻繁地調(diào)用,那么就很有可能會(huì)發(fā)生內(nèi)存抖動(dòng)革为。這里我們新版本已經(jīng)改為使用stringbuilder進(jìn)行優(yōu)化
5:屬性動(dòng)畫(huà)扭粱,無(wú)限循環(huán)的情況,在Activity的onDestroy()中需要調(diào)用animator.cancel();
6:方法深度不易過(guò)大震檩,棧深度過(guò)大就會(huì)導(dǎo)致棧溢出琢蛤。一個(gè)線程的棧深度定義方式有兩種,指定大小和動(dòng)態(tài)申請(qǐng)。指定大信翱椤:如果超過(guò)此大小會(huì)報(bào)棧溢出俩滥。動(dòng)態(tài)申請(qǐng):棧大小不足時(shí)嘉蕾,就會(huì)申請(qǐng)更大深度的棧贺奠。如 果申請(qǐng)的大小超過(guò)了java虛擬機(jī)最大承受范圍,也會(huì)報(bào)棧溢出
7:handler消息未清理
8:內(nèi)部類(lèi)错忱,對(duì)象持有
9:?jiǎn)卫苈剩瑔卫侨值模绻渲谐钟芯哂猩芷诘膶?duì)象以清,就會(huì)導(dǎo)致此對(duì)象不會(huì)被釋放儿普,例如Context持有的是Activity
10:耗時(shí)任務(wù),開(kāi)Thread的掷倔,把Runnable放到線程池中執(zhí)行
11:webview頁(yè)面做獨(dú)立進(jìn)程
12:靜態(tài)代碼塊中不能做耗時(shí)任務(wù)眉孩,類(lèi)加載的初始化階段,執(zhí)行類(lèi)構(gòu)造器方法勒葱,類(lèi)構(gòu)造器中執(zhí)行靜態(tài)成員變量初始化和靜態(tài)代碼塊浪汪,如果做耗時(shí)任務(wù),會(huì)使當(dāng)前線程類(lèi)的加載時(shí)間過(guò)長(zhǎng)凛虽。并且類(lèi)構(gòu)造器執(zhí)行是 ? 線程安全的死遭,假如有多線程訪問(wèn),就會(huì)造成其他線程長(zhǎng)時(shí)間阻塞凯旋。
13:android資源訪問(wèn)未關(guān)閉呀潭,BraodcastReceiver,Cursor至非,IO Stream钠署,退出app時(shí)數(shù)據(jù)庫(kù)未關(guān)閉,Bitmap使用完要手動(dòng)回收
14:ListView荒椭,RecyclerView使用時(shí)ItemView復(fù)用
15:序列化存儲(chǔ)到本地時(shí)用Serializable踏幻;內(nèi)存中的數(shù)據(jù)傳遞,序列化使用Parcelable戳杀,因?yàn)镾erializable在序列化時(shí)會(huì)產(chǎn)生大量臨時(shí)變量该面,引起頻繁的GC
16:第三方庫(kù)的引用,要謹(jǐn)慎信卡,庫(kù)文件打包時(shí)也會(huì)被打包到相應(yīng)的dex中隔缀,dex的加載是在Application的onBaseContext()中,也會(huì)消耗一點(diǎn)加載時(shí)間和內(nèi)存傍菇。如果僅僅為了使用一個(gè)庫(kù)中的一兩個(gè)方法就隨意引入龐大的庫(kù)猾瘸,代價(jià)也是不小的。
17:SVG的使用,項(xiàng)目中配置型icon使用
18:Fragment懶加載和不可見(jiàn)時(shí)定時(shí)回收數(shù)據(jù)
1)Fragment+ViewPager形式牵触,初始化時(shí)如果可見(jiàn)則調(diào)用onCreatView()淮悼,不可見(jiàn)初始化時(shí)onCreatView()則返回一個(gè)空view,等第一次可見(jiàn)再加載view布局
2)母嬰之家的社交模塊揽思,是由三個(gè)Tab組成袜腥,其中帖子Tab全是大圖,處理方法是Fragment不可見(jiàn)2秒后認(rèn)為此頁(yè)面用戶暫時(shí)不操作钉汗,就會(huì)清空Adapter中的數(shù)據(jù)羹令,等再切回到此頁(yè)面時(shí),再重新裝填 內(nèi)存中的數(shù)據(jù)
19:?jiǎn)?dòng)優(yōu)化:
? ? 1)application中onCreate()不能執(zhí)行耗時(shí)操作损痰,否則會(huì)影響SpleshActivity的啟動(dòng)
? ? 2)onPause()中不能執(zhí)行耗時(shí)操作福侈,否則會(huì)延遲被啟動(dòng)頁(yè)面的顯示
20:圖片大圖優(yōu)化
項(xiàng)目中內(nèi)存泄漏檢測(cè)工具用的是LeakCanary,在測(cè)試代碼塊時(shí)可以及時(shí)發(fā)現(xiàn)內(nèi)存泄漏卢未,并且以UI方式顯示肪凛,更為直觀。使用LeakCanary后辽社,項(xiàng)目?jī)?nèi)存有時(shí)還是很客觀伟墙,但一般只發(fā)生在特定階段,此時(shí)可以用Android Profiler查找原因爹袁。項(xiàng)目中例子:
1)OCR身份證圖片使用完未回收远荠,有6MB的優(yōu)化
2)新股列表Adapter中采用單例模式,并持有Activity引用
3)webview獨(dú)立進(jìn)程