偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

【寶貴經(jīng)驗(yàn)】Android性能優(yōu)化之內(nèi)存優(yōu)化實(shí)戰(zhàn)

移動(dòng)開(kāi)發(fā) Android
Android系統(tǒng)的每個(gè)進(jìn)程都有一個(gè)最大內(nèi)存限制,如果申請(qǐng)的內(nèi)存資源超過(guò)這個(gè)限制,系統(tǒng)就會(huì)拋出OOM錯(cuò)誤。內(nèi)存溢出是程序運(yùn)行到某一階段的最終結(jié)果,直接原因是剩余的內(nèi)存不能滿足內(nèi)存的申請(qǐng)。

1. Memory Leak

內(nèi)存泄漏:對(duì)于Java來(lái)說(shuō),就是new出來(lái)的Object 放在Heap上無(wú)法被GC回收(內(nèi)存中存在無(wú)法被回收的對(duì)象);內(nèi)存泄漏發(fā)生時(shí)的主要表現(xiàn)為內(nèi)存抖動(dòng),可用內(nèi)存慢慢變少。

1.1 Memory Monitor

AndroidStudio自帶的Memory Monitor可以方便的觀察堆內(nèi)存的分配情況,并且可以粗略的觀察有沒(méi)有Memory Leak。 

 

 

 

頻繁的內(nèi)存抖動(dòng),可能存在內(nèi)存泄漏

A:initiate GC 手動(dòng)觸發(fā)GC操作;

B:Dump Java Heap 獲取當(dāng)前的堆棧信息,生成一個(gè).hprof文件,AndroidStudip會(huì)自動(dòng)使用HeapViewer打開(kāi);一般用于操作之后檢測(cè)內(nèi)存泄漏的情況;

C:Start Allocation Tracking 內(nèi)存分配追蹤工具,用于追蹤一段時(shí)間的內(nèi)存分配使用情況,能夠知道執(zhí)行一些列操作后,有哪些對(duì)象被分配空間。一般用于追蹤某項(xiàng)操作之后的內(nèi)存分配,調(diào)整相關(guān)的方法調(diào)用來(lái)優(yōu)化app性能與內(nèi)存使用;

D:剩余可用內(nèi)存;

E:已經(jīng)使用的內(nèi)存。

點(diǎn)擊Memory Monitor的Dump Java Heap,會(huì)生成一個(gè).hprof文件,AndroidStudio會(huì)自動(dòng)使用HeapViewer打開(kāi)。 

 

 

 

Hprof Viewer打開(kāi).hprof文件

左面板說(shuō)明:

  • Total Count 該類(lèi)的實(shí)例個(gè)數(shù)
  • Heap Count 選定的Heap中實(shí)例的個(gè)數(shù)
  • Sizeof 每個(gè)實(shí)例占用的內(nèi)存大小
  • Shallow Size 所有該類(lèi)的實(shí)例占用的內(nèi)存大小
  • Retained Size 該類(lèi)的所有實(shí)例可支配的內(nèi)存大小

右面板說(shuō)明:

  • Instance 該類(lèi)的所有實(shí)例對(duì)象(左側(cè)Total Count為15,此處就有15個(gè)對(duì)象)
  • Depth 深度, GC Root點(diǎn)到該實(shí)例的最短鏈路數(shù)
  • Dominating Size 該實(shí)例可支配的內(nèi)存大小

此處可以看出MainActivity存在了15個(gè)示例對(duì)象,懷疑此處有問(wèn)題。

1.2 MAT

上述只是可以粗略的看出是不是有問(wèn)題,而要知道問(wèn)題出在哪里就需要借助MAT了。將生成的.hprof文件進(jìn)行轉(zhuǎn)換,然后使用MAT打開(kāi);

格式轉(zhuǎn)換命令:hprof-conv 原文件路徑 轉(zhuǎn)換后文件路徑 

 

 

 

MAT打開(kāi).hprof

注意下面的Actions:

  • Histogram可以列出內(nèi)存中每個(gè)對(duì)象的名字、數(shù)量以及大小。
  • Dominator Tree會(huì)將所有內(nèi)存中的對(duì)象按大小進(jìn)行排序,并且我們可以分析對(duì)象之間的引用結(jié)構(gòu)。

一般使用最多的也是這兩個(gè)功能。

Retained Heap表示這個(gè)對(duì)象以及它所持有的其它引用(包括直接和間接)所占的總內(nèi)存

  • 使用Histogram:
  • 點(diǎn)擊Histogram并在頂部的Regex中輸入MainActivity會(huì)進(jìn)行正則匹配,會(huì)將包含“MainActivity”的所有對(duì)象全部列出了出來(lái),其中***行就是MainActivity的實(shí)例。 

 

 

 

  • 對(duì)著想查看的對(duì)象點(diǎn)擊右鍵 -> List objects -> with incoming references 查看具體MainActivity實(shí)例。 

 

 

 

  • 對(duì)想要查看的對(duì)象實(shí)例點(diǎn)擊右鍵-> Path To Gc Roots -> exclude weak reference(排除掉軟引用)。 

 

 

 

注意:

this$0前面的圖標(biāo)的左下角有個(gè)圓圈,這代表這個(gè)引用可以被Gc Roots引用到,由于MainActivity$LeakClass能被GC Roots訪問(wèn)到導(dǎo)致其不能被回收,從而它所持有的其它引用也無(wú)法被回收了,包括MainActivity,也包括MainActivity中所包含的其它資源。

此時(shí)我們就找到了內(nèi)存泄漏的原因。

  • 使用Dominator Tree 

 

 

 

使用上面Histogram的操作方式也可以找到泄漏的具體原因,此處不再累述。

注意:每個(gè)對(duì)象前的圖標(biāo)的圓圈,并不代表一定是導(dǎo)致內(nèi)存泄漏的原因,有些對(duì)象就是需要在內(nèi)存中存活的,需要區(qū)別對(duì)待。

1.3 LeakCanary

LeakCanary是square出品的一個(gè)檢測(cè)內(nèi)存泄漏的庫(kù),集成到App之后便無(wú)需關(guān)心,在發(fā)生內(nèi)存泄漏之后會(huì)Toast、通知欄彈出等方式提示,可以指出泄漏的引用路徑,而且可以抓取當(dāng)前的堆棧信息供詳細(xì)分析。 

 

 

 

2. Out Of Memory

2.1 Android OOM

Android系統(tǒng)的每個(gè)進(jìn)程都有一個(gè)***內(nèi)存限制,如果申請(qǐng)的內(nèi)存資源超過(guò)這個(gè)限制,系統(tǒng)就會(huì)拋出OOM錯(cuò)誤。

  • Android 2.x系統(tǒng),當(dāng)dalvik allocated + external allocated + 新分配的大小 >= dalvik heap ***值時(shí)候就會(huì)發(fā)生OOM。其中bitmap是放于external中 。
  • Android 4.x系統(tǒng),廢除了external的計(jì)數(shù)器,類(lèi)似bitmap的分配改到dalvik的java heap中申請(qǐng),只要allocated + 新分配的內(nèi)存 >= dalvik heap ***值的時(shí)候就會(huì)發(fā)生OOM(art運(yùn)行環(huán)境的統(tǒng)計(jì)規(guī)則還是和dalvik保持一致)

內(nèi)存溢出是程序運(yùn)行到某一階段的最終結(jié)果,直接原因是剩余的內(nèi)存不能滿足內(nèi)存的申請(qǐng),但是再分析間接原因內(nèi)存為什么沒(méi)有了:

  • 內(nèi)存泄漏的存在可能導(dǎo)致可用內(nèi)存越來(lái)越少;
  • 內(nèi)存申請(qǐng)的峰值超過(guò)了系統(tǒng)時(shí)間點(diǎn)剩余的內(nèi)存;(例如:某手機(jī)單個(gè)進(jìn)程可用***內(nèi)存為192M,目前分配內(nèi)存80M,此時(shí)申請(qǐng)5M內(nèi)存,但是當(dāng)前時(shí)間點(diǎn)整個(gè)系統(tǒng)可用內(nèi)存只有3M,此時(shí)沒(méi)有超出單個(gè)進(jìn)程可用***內(nèi)存,但是OOM也會(huì)發(fā)生)

2.2 Avoid Android OOM

除了避免內(nèi)存泄漏之外,根據(jù)《Manage Your App's Memory》,我們可以對(duì)內(nèi)存的狀態(tài)進(jìn)行監(jiān)聽(tīng),在Activity中覆寫(xiě)此方法,根據(jù)不同的case進(jìn)行不同的處理:

  1. @Override 
  2.     public void onTrimMemory(int level) {        super.onTrimMemory(level); 
  3.     }  

TRIM_MEMORY_RUNNING_MODERATE:你的應(yīng)用正在運(yùn)行并且不會(huì)被列為可殺死的。但是設(shè)備此時(shí)正運(yùn)行于低內(nèi)存狀態(tài)下,系統(tǒng)開(kāi)始觸發(fā)殺死LRU Cache中的Process的機(jī)制。

TRIM_MEMORY_RUNNING_LOW:你的應(yīng)用正在運(yùn)行且沒(méi)有被列為可殺死的。但是設(shè)備正運(yùn)行于更低內(nèi)存的狀態(tài)下,你應(yīng)該釋放不用的資源用來(lái)提升系統(tǒng)性能。

TRIM_MEMORY_RUNNING_CRITICAL:你的應(yīng)用仍在運(yùn)行,但是系統(tǒng)已經(jīng)把LRU Cache中的大多數(shù)進(jìn)程都已經(jīng)殺死,因此你應(yīng)該立即釋放所有非必須的資源。如果系統(tǒng)不能回收到足夠的RAM數(shù)量,系統(tǒng)將會(huì)清除所有的LRU緩存中的進(jìn)程,并且開(kāi)始?xì)⑺滥切┲氨徽J(rèn)為不應(yīng)該殺死的進(jìn)程,例如那個(gè)包含了一個(gè)運(yùn)行態(tài)Service的進(jìn)程。

當(dāng)應(yīng)用進(jìn)程退到后臺(tái)正在被Cached的時(shí)候,可能會(huì)接收到從onTrimMemory()中返回的下面的值之一:

TRIM_MEMORY_BACKGROUND: 系統(tǒng)正運(yùn)行于低內(nèi)存狀態(tài)并且你的進(jìn)程正處于LRU緩存名單中最不容易殺掉的位置。盡管你的應(yīng)用進(jìn)程并不是處于被殺掉的高危險(xiǎn)狀態(tài),系統(tǒng)可能已經(jīng)開(kāi)始?xì)⒌鬖RU緩存中的其他進(jìn)程了。你應(yīng)該釋放那些容易恢復(fù)的資源,以便于你的進(jìn)程可以保留下來(lái),這樣當(dāng)用戶(hù)回退到你的應(yīng)用的時(shí)候才能夠迅速恢復(fù)。

TRIM_MEMORY_MODERATE: 系統(tǒng)正運(yùn)行于低內(nèi)存狀態(tài)并且你的進(jìn)程已經(jīng)已經(jīng)接近LRU名單的中部位置。如果系統(tǒng)開(kāi)始變得更加內(nèi)存緊張,你的進(jìn)程是有可能被殺死的。

TRIM_MEMORY_COMPLETE: 系統(tǒng)正運(yùn)行于低內(nèi)存的狀態(tài)并且你的進(jìn)程正處于LRU名單中最容易被殺掉的位置。你應(yīng)該釋放任何不影響你的應(yīng)用恢復(fù)狀態(tài)的資源。

3. Memory Churn

Memory Churn內(nèi)存抖動(dòng):大量的對(duì)象被創(chuàng)建又在短時(shí)間內(nèi)馬上被釋放。

瞬間產(chǎn)生大量的對(duì)象會(huì)嚴(yán)重占用Young Generation的內(nèi)存區(qū)域,當(dāng)達(dá)到閥值,剩余空間不夠的時(shí)候,也會(huì)觸發(fā)GC。系統(tǒng)花費(fèi)在GC上的時(shí)間越多,進(jìn)行界面繪制或流音頻處理的時(shí)間就越短。即使每次分配的對(duì)象占用了很少的內(nèi)存,但是他們疊加在一起會(huì)增加Heap的壓力,從而觸發(fā)更多其他類(lèi)型的GC。這個(gè)操作有可能會(huì)影響到幀率,并使得用戶(hù)感知到性能問(wèn)題。 

 

 

 

Drop Frame Occur

常見(jiàn)的可能引發(fā)內(nèi)存抖動(dòng)的情形:

  • 循環(huán)中創(chuàng)建臨時(shí)對(duì)象;
  • onDraw中創(chuàng)建Paint或Bitmap對(duì)象等;

例如之前使用過(guò)的有些下拉刷新控件的實(shí)現(xiàn)方式,在onDraw中創(chuàng)建Bitmap等多個(gè)臨時(shí)大對(duì)象會(huì)導(dǎo)致內(nèi)存抖動(dòng)。

4. Bitmap

Bitmap的處理也是Android中的一個(gè)難點(diǎn),當(dāng)然使用第三方框架的話就屏蔽掉了這個(gè)難點(diǎn)。

  • Bitmap的內(nèi)存模型;
  • Bitmap的加載、壓縮、緩存等策略;
  • 版本的兼容等;

關(guān)于Bitmap之后會(huì)寫(xiě)專(zhuān)門(mén)的一篇文章來(lái)介紹,此處可以參考《Handling Bitmaps》。

5. Program Advice

5.1 節(jié)制地使用Service

內(nèi)存管理***的錯(cuò)誤之一就是讓Service一直運(yùn)行。在后臺(tái)使用service時(shí),除非它需要被觸發(fā)并執(zhí)行一個(gè)任務(wù),否則其他時(shí)候Service都應(yīng)該是停止?fàn)顟B(tài)。另外需要注意Service工作完畢之后需要被停止,以免造成內(nèi)存泄漏。

系統(tǒng)會(huì)傾向于保留有Service所在的進(jìn)程,這使得進(jìn)程的運(yùn)行代價(jià)很高,因?yàn)橄到y(tǒng)沒(méi)有辦法把Service所占用的RAM空間騰出來(lái)讓給其他組件,另外Service還不能被Paged out。這減少了系統(tǒng)能夠存放到LRU緩存當(dāng)中的進(jìn)程數(shù)量,它會(huì)影響應(yīng)用之間的切換效率,甚至?xí)?dǎo)致系統(tǒng)內(nèi)存使用不穩(wěn)定,從而無(wú)法繼續(xù)保持住所有目前正在運(yùn)行的service。

建議使用JobScheduler,而盡量避免使用持久性的Service。還有建議使用IntentService,它會(huì)在處理完交代給它的任務(wù)之后盡快結(jié)束自己。

5.2 使用優(yōu)化過(guò)的集合

Android API當(dāng)中提供了一些優(yōu)化過(guò)后的數(shù)據(jù)集合工具類(lèi),如SparseArray,SparseBooleanArray,以及LongSparseArray等,使用這些API可以讓我們的程序更加高效。傳統(tǒng)Java API中提供的HashMap工具類(lèi)會(huì)相對(duì)比較低效,因?yàn)樗枰獮槊恳粋€(gè)鍵值對(duì)都提供一個(gè)對(duì)象入口,而SparseArray就避免掉了基本數(shù)據(jù)類(lèi)型轉(zhuǎn)換成對(duì)象數(shù)據(jù)類(lèi)型的時(shí)間。

5.3 謹(jǐn)慎對(duì)待面向抽象

開(kāi)發(fā)者經(jīng)常把抽象作為好的編程實(shí)踐,因?yàn)槌橄竽軌蛱嵘a的靈活性與可維護(hù)性。然而,抽象會(huì)導(dǎo)致一個(gè)顯著的開(kāi)銷(xiāo):面向抽象需要額外的代碼(不會(huì)被執(zhí)行到),同樣會(huì)被咨映射到內(nèi)存中,耗費(fèi)了更多的時(shí)間以及內(nèi)存空間。因此如果面向抽象對(duì)你的代碼沒(méi)有顯著的收益,那你應(yīng)該避免使用。

例如:使用枚舉通常會(huì)比使用靜態(tài)常量要消耗兩倍以上的內(nèi)存,在Android開(kāi)發(fā)當(dāng)中我們應(yīng)當(dāng)盡可能地不使用枚舉。

5.4 使用nano protobufs序列化數(shù)據(jù)

Protocol buffers是Google為序列化數(shù)據(jù)設(shè)計(jì)的一種語(yǔ)言無(wú)關(guān)、平臺(tái)無(wú)關(guān)、具有良好擴(kuò)展性的數(shù)據(jù)描述語(yǔ)言,與XML類(lèi)似,但是更加輕量、快速、簡(jiǎn)單。如果使用protobufs來(lái)實(shí)現(xiàn)數(shù)據(jù)的序列化及反序列化,建議在客戶(hù)端使用nano protobufs,因?yàn)橥ǔ5膒rotobufs會(huì)生成冗余代碼,會(huì)導(dǎo)致可用內(nèi)存減少,Apk體積變大,運(yùn)行速度減慢。

5.5 避免內(nèi)存抖動(dòng)

垃圾回收通常不會(huì)影響應(yīng)用的表現(xiàn),但是短時(shí)間內(nèi)多次的垃圾回收會(huì)消耗掉界面繪制的時(shí)間。系統(tǒng)花費(fèi)在GC上的時(shí)間越多,進(jìn)行界面繪制或流音頻處理的時(shí)間就越短。通常內(nèi)存抖動(dòng)會(huì)導(dǎo)致多次的GC,實(shí)踐中內(nèi)存抖動(dòng)代表了一段時(shí)間內(nèi)分配了臨時(shí)對(duì)象。

例如:在For循環(huán)中分配了多個(gè)臨時(shí)對(duì)象,或在onDraw()方法中創(chuàng)建了Paint、Bitmap對(duì)象,應(yīng)用產(chǎn)生了大量的對(duì)象;這會(huì)很快耗盡young generation的可用內(nèi)存,導(dǎo)致GC發(fā)生。

使用Analyze your RAM usage中的工具找出代碼里內(nèi)存抖動(dòng)的地方??紤]把操作移出內(nèi)部循環(huán),或者將其移動(dòng)到基于工廠的分配結(jié)構(gòu)中。

5.6 移除消耗內(nèi)存的庫(kù)、縮減Apk的大小

查看Apk的大小,包括三方庫(kù)和內(nèi)嵌的資源,這些都會(huì)影響應(yīng)用消耗的內(nèi)存。通過(guò)減少冗余、非必須或大的組件、庫(kù)、圖片、資源、動(dòng)畫(huà)等,都可以改善應(yīng)用的內(nèi)存消耗。

5.7 使用Dagger 2進(jìn)行依賴(lài)注入

如果您打算在應(yīng)用程序中使用依賴(lài)注入框架,請(qǐng)考慮使用Dagger 2。 Dagger不使用反射來(lái)掃描應(yīng)用程序的代碼。 Dagger的編譯時(shí)注解技術(shù)實(shí)現(xiàn)意味著它不需要不必要的運(yùn)行時(shí)成本。而使用反射的其它依賴(lài)注入框架通常通過(guò)掃描代碼來(lái)初始化過(guò)程。 此過(guò)程可能需要顯著更多的CPU周期和RAM,并可能導(dǎo)致應(yīng)用程序啟動(dòng)時(shí)明顯的卡頓。

備注:之前的文檔是不建議使用依賴(lài)注入框架,因?yàn)閷?shí)現(xiàn)原理是使用反射,而進(jìn)化為編譯時(shí)注解之后,就不再有反射帶來(lái)的影響了。

5.8 謹(jǐn)慎使用第三方庫(kù)

很多開(kāi)源的library代碼都不是為移動(dòng)端而編寫(xiě)的,如果運(yùn)用在移動(dòng)設(shè)備上,并不一定適合。即使是針對(duì)Android而設(shè)計(jì)的library,也需要特別謹(jǐn)慎,特別是在你不知道引入的library具體做了什么事情的時(shí)候。例如,其中一個(gè)library使用的是nano protobufs, 而另外一個(gè)使用的是micro protobufs。這樣一來(lái),在你的應(yīng)用里面就有2種protobuf的實(shí)現(xiàn)方式。這樣類(lèi)似的沖突還可能發(fā)生在輸出日志,加載圖片,緩存等等模塊里面。另外不要為了1個(gè)或者2個(gè)功能而導(dǎo)入整個(gè)library,如果沒(méi)有一個(gè)合適的庫(kù)與你的需求相吻合,你應(yīng)該考慮自己去實(shí)現(xiàn),而不是導(dǎo)入一個(gè)大而全的解決方案。

6. Other

6.1 謹(jǐn)慎使用LargeHeap屬性

可以通過(guò)在manifest的application標(biāo)簽下添加largeHeap=true的屬性來(lái)為應(yīng)用聲明一個(gè)更大的heap空間(可以通過(guò)getLargeMemoryClass()來(lái)獲取到這個(gè)更大的heap size閾值)。然而,聲明得到更大Heap閾值的本意是為了一小部分會(huì)消耗大量RAM的應(yīng)用(例如一個(gè)大圖片的編輯應(yīng)用)。不要輕易的因?yàn)槟阈枰褂酶嗟膬?nèi)存而去請(qǐng)求一個(gè)大的Heap Size。只有當(dāng)你清楚的知道哪里會(huì)使用大量的內(nèi)存并且知道為什么這些內(nèi)存必須被保留時(shí)才去使用large heap,使用額外的內(nèi)存空間會(huì)影響系統(tǒng)整體的用戶(hù)體驗(yàn),并且會(huì)使得每次gc的運(yùn)行時(shí)間更長(zhǎng)。在任務(wù)切換時(shí),系統(tǒng)的性能會(huì)大打折扣。另外, large heap并不一定能夠獲取到更大的heap。在某些有嚴(yán)格限制的機(jī)器上,large heap的大小和通常的heap size是一樣的。

6.2 謹(jǐn)慎使用多進(jìn)程

多進(jìn)程確實(shí)是一種可以幫助我們節(jié)省和管理內(nèi)存的高級(jí)技巧。如果你要使用它的話一定要謹(jǐn)慎使用,因?yàn)榻^大多數(shù)的應(yīng)用程序都不應(yīng)該在多個(gè)進(jìn)程當(dāng)中運(yùn)行的,一旦使用不當(dāng),它甚至?xí)黾宇~外的內(nèi)存而不是幫我們節(jié)省內(nèi)存;同時(shí)需要知曉多進(jìn)程帶來(lái)的缺點(diǎn)。這個(gè)技巧比較適用于那些需要在后臺(tái)去完成一項(xiàng)獨(dú)立的任務(wù),和前臺(tái)的功能是可以完全區(qū)分開(kāi)的場(chǎng)景。

這里舉一個(gè)比較適合去使用多進(jìn)程技巧的場(chǎng)景,比如說(shuō)我們正在做一個(gè)音樂(lè)播放器軟件,其中播放音樂(lè)的功能應(yīng)該是一個(gè)獨(dú)立的功能,它不需要和UI方面有任何關(guān)系,即使軟件已經(jīng)關(guān)閉了也應(yīng)該可以正常播放音樂(lè)。如果此時(shí)我們只使用一個(gè)進(jìn)程,那么即使用戶(hù)關(guān)閉了軟件,已經(jīng)完全由Service來(lái)控制音樂(lè)播放了,系統(tǒng)仍然會(huì)將許多UI方面的內(nèi)存進(jìn)行保留。在這種場(chǎng)景下就非常適合使用兩個(gè)進(jìn)程,一個(gè)用于UI展示,另一個(gè)則用于在后臺(tái)持續(xù)地播放音樂(lè)。

6.3 實(shí)現(xiàn)方式可能存在的問(wèn)題:例如啟動(dòng)頁(yè)閃屏圖,show完畢之后應(yīng)該釋放掉Bitmap。

一些實(shí)現(xiàn)方式看起來(lái)沒(méi)有問(wèn)題實(shí)現(xiàn)了功能但是實(shí)際上可能對(duì)內(nèi)存造成了影響。我在使用Heap Viewer查看Bitmap對(duì)象時(shí)發(fā)現(xiàn)了一張只需下載不應(yīng)該被加載的圖。 

 

 

 

使用HeapViewer可直接查看Bitmap 

 

 

 

內(nèi)存中出現(xiàn)的不應(yīng)該被加載的圖

通過(guò)查閱代碼,發(fā)現(xiàn)問(wèn)題出在:此處下載圖片作為另一個(gè)模塊的使用圖,但是下載的方法竟然是使用圖片加載器加載出來(lái)Bitmap然后再保存到本地;而且保存之后也沒(méi)有將Bitmap對(duì)象釋放掉。

與之類(lèi)似的還有:首頁(yè)閃屏圖展示之后,Bitmap對(duì)象應(yīng)該及時(shí)釋放掉。

6.4 使用try catch進(jìn)行捕獲

對(duì)高風(fēng)險(xiǎn)OOM代碼塊如展示高清大圖等進(jìn)行try catch,在catch塊加載非高清的圖片并做相應(yīng)內(nèi)存回收的處理。注意OOM是OutOfMemoryError,不能使用Exception進(jìn)行捕獲。

7. Summary

內(nèi)存優(yōu)化的套路:

(1)解決所有的內(nèi)存泄漏

  • 集成LeakCanary,可以方便的定位出90%的內(nèi)存泄漏問(wèn)題;
  • 通過(guò)反復(fù)進(jìn)出可疑界面,觀察內(nèi)存增減的情況,Dump Java Heap獲取當(dāng)前堆棧信息使用MAT進(jìn)行分析。
  • 內(nèi)存泄漏的常見(jiàn)情形可參照《Android 內(nèi)存泄漏分析心得》

(2)避免內(nèi)存抖動(dòng)

  • 避免在循環(huán)中創(chuàng)建臨時(shí)對(duì)象;
  • 避免在onDraw中創(chuàng)建Paint、Bitmap對(duì)象等。

(3)Bitmap的使用

  • 使用三方庫(kù)加載圖片一般不會(huì)出內(nèi)存問(wèn)題,但是需要注意圖片使用完畢的釋放,而不是被動(dòng)等待釋放。
  • 使用優(yōu)化過(guò)的數(shù)據(jù)結(jié)構(gòu)
  • 使用onTrimMemory根據(jù)不同的內(nèi)存狀態(tài)做相應(yīng)處理

(4)Library的使用

  • 去掉無(wú)用的Library,對(duì)生成的Apk進(jìn)行反編譯查看使用到的Library,避免出現(xiàn)無(wú)用的Lib仍然被打進(jìn)Apk;
  • 避免引入巨大的Library;
  • 使用Proguard進(jìn)行混淆、壓縮。
責(zé)任編輯:龐桂玉 來(lái)源: Android技術(shù)之家
相關(guān)推薦

2015-09-16 15:21:23

Android性能優(yōu)化內(nèi)存

2016-12-22 17:21:11

Android性能優(yōu)化內(nèi)存泄漏

2019-12-13 10:25:08

Android性能優(yōu)化啟動(dòng)優(yōu)化

2010-07-06 16:22:14

2009-09-22 17:25:41

優(yōu)化Hibernate

2017-03-29 14:44:20

網(wǎng)絡(luò)性能優(yōu)化

2022-05-17 09:02:30

前端性能優(yōu)化

2011-07-28 10:01:19

IOS 內(nèi)存優(yōu)化

2011-06-20 13:35:01

網(wǎng)站優(yōu)化

2009-04-20 08:51:50

MySQL查詢(xún)優(yōu)化數(shù)據(jù)庫(kù)

2010-02-23 16:17:59

2018-05-09 08:35:59

2011-12-28 13:38:00

JavaJVM

2012-01-10 16:22:25

Web

2009-12-16 15:23:33

Ruby on rai

2009-12-24 16:46:03

WPF性能優(yōu)化

2021-07-29 14:20:34

網(wǎng)絡(luò)優(yōu)化移動(dòng)互聯(lián)網(wǎng)數(shù)據(jù)存儲(chǔ)

2019-07-25 13:22:43

AndroidAPK文件優(yōu)化

2013-09-16 15:16:20

Android性能優(yōu)化

2023-06-12 00:22:50

操作系統(tǒng)應(yīng)用程序內(nèi)核鎖
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)