常用的Android性能優(yōu)化方法:
創(chuàng)新互聯(lián)成立十載來(lái),這條路我們正越走越好,積累了技術(shù)與客戶(hù)資源,形成了良好的口碑。為客戶(hù)提供成都做網(wǎng)站、成都網(wǎng)站制作、網(wǎng)站策劃、網(wǎng)頁(yè)設(shè)計(jì)、國(guó)際域名空間、網(wǎng)絡(luò)營(yíng)銷(xiāo)、VI設(shè)計(jì)、網(wǎng)站改版、漏洞修補(bǔ)等服務(wù)。網(wǎng)站是否美觀、功能強(qiáng)大、用戶(hù)體驗(yàn)好、性?xún)r(jià)比高、打開(kāi)快等等,這些對(duì)于網(wǎng)站建設(shè)都非常重要,創(chuàng)新互聯(lián)通過(guò)對(duì)建站技術(shù)性的掌握、對(duì)創(chuàng)意設(shè)計(jì)的研究為客戶(hù)提供一站式互聯(lián)網(wǎng)解決方案,攜手廣大客戶(hù),共同發(fā)展進(jìn)步。
一、布局優(yōu)化:
1)盡量減少布局文件的層級(jí)。
層級(jí)少了,繪制的工作量也就少了,性能自然提高。
2)布局重用 include標(biāo)簽
3)按需加載:使用ViewStub,它繼承自View,一種輕量級(jí)控件,本身不參與任何的布局和繪制過(guò)程。他的layout參數(shù)里添加一個(gè)替換的布局文件,當(dāng)它通過(guò)setVisibility或者inflate方法加載后,它就會(huì)被內(nèi)部布局替換掉。
二、繪制優(yōu)化:
基于onDraw會(huì)被調(diào)用多次,該方法內(nèi)要避免兩類(lèi)操作:
1)創(chuàng)建新的局部對(duì)象,導(dǎo)致大量垃圾對(duì)象的產(chǎn)生,從而導(dǎo)致頻繁的gc,降低程序的執(zhí)行效率。
2)不要做耗時(shí)操作,搶CPU時(shí)間片,造成繪制很卡不流暢。
三、內(nèi)存泄漏優(yōu)化:
1)靜態(tài)變量導(dǎo)致內(nèi)存泄漏 ? 比較明顯
2)單例模式導(dǎo)致的內(nèi)存泄漏?單例無(wú)法被垃圾回收,它持有的任何對(duì)象的引用都會(huì)導(dǎo)致該對(duì)象不會(huì)被gc。
3)屬性動(dòng)畫(huà)導(dǎo)致內(nèi)存泄漏 ?無(wú)限循環(huán)動(dòng)畫(huà),在activity中播放,但是onDestroy時(shí)沒(méi)有停止的話(huà),動(dòng)畫(huà)會(huì)一直播放下去,view被動(dòng)畫(huà)持有,activity又被view持有,導(dǎo)致activity無(wú)法被回收。
四、響應(yīng)速度優(yōu)化:
1)避免在主線(xiàn)程做耗時(shí)操作 包括四大組件,因?yàn)樗拇蠼M件都是運(yùn)行在主線(xiàn)程的。
2)把一些創(chuàng)建大量對(duì)象等的初始化工作放在頁(yè)面回到前臺(tái)之后,而不應(yīng)該放到創(chuàng)建的時(shí)候。
五、ListView的優(yōu)化:
1)使用convertView,走listView子View回收的一套:RecycleBin 機(jī)制
主要是維護(hù)了兩個(gè)數(shù)組,一個(gè)是mActiveViews,當(dāng)前可見(jiàn)的view,一個(gè)是mScrapViews,當(dāng)前不可見(jiàn)的view。當(dāng)觸摸ListView并向上滑動(dòng)時(shí),ListView上部的一些OnScreen的View位置上移,并移除了ListView的屏幕范圍,此時(shí)這些OnScreen的View就變得不可見(jiàn)了,不可見(jiàn)的View叫做OffScreen的View,即這些View已經(jīng)不在屏幕可見(jiàn)范圍內(nèi)了,也可以叫做ScrapView,Scrap表示廢棄的意思,ScrapView的意思是這些OffScreen的View不再處于可以交互的Active狀態(tài)了。ListView會(huì)把那些ScrapView(即OffScreen的View)刪除,這樣就不用繪制這些本來(lái)就不可見(jiàn)的View了,同時(shí),ListView會(huì)把這些刪除的ScrapView放入到RecycleBin中存起來(lái),就像把暫時(shí)無(wú)用的資源放到回收站一樣。
當(dāng)ListView的底部需要顯示新的View的時(shí)候,會(huì)從RecycleBin中取出一個(gè)ScrapView,將其作為convertView參數(shù)傳遞給Adapter的getView方法,從而達(dá)到View復(fù)用的目的,這樣就不必在Adapter的getView方法中執(zhí)行LayoutInflater.inflate()方法了。
RecycleBin中有兩個(gè)重要的View數(shù)組,分別是mActiveViews和mScrapViews。這兩個(gè)數(shù)組中所存儲(chǔ)的View都是用來(lái)復(fù)用的,只不過(guò)mActiveViews中存儲(chǔ)的是OnScreen的View,這些View很有可能被直接復(fù)用;而mScrapViews中存儲(chǔ)的是OffScreen的View,這些View主要是用來(lái)間接復(fù)用的。
2)使用ViewHolder避免重復(fù)地findViewById
3)快速滑動(dòng)不適合做大量異步任務(wù),結(jié)合滑動(dòng)監(jiān)聽(tīng),等滑動(dòng)結(jié)束之后加載當(dāng)前顯示在屏幕范圍的內(nèi)容。
4)getView中避免做耗時(shí)操作,主要針對(duì)圖片:ImageLoader來(lái)處理(原理:三級(jí)緩存)
5)對(duì)于一個(gè)列表,如果刷新數(shù)據(jù)只是某一個(gè)item的數(shù)據(jù),可以使用局部刷新,在列表數(shù)據(jù)量比較大的情況下,節(jié)省不少性能開(kāi)銷(xiāo)。
六、Bitmap優(yōu)化:
1)減少內(nèi)存開(kāi)支:圖片過(guò)大,超過(guò)控件需要的大小的情況下,不要直接加載原圖,而是對(duì)圖片進(jìn)行尺寸壓縮,方式是BitmapFactroy.Options 采樣,inSampleSize 轉(zhuǎn)成需要的尺寸的圖片。
2)減少流量開(kāi)銷(xiāo):對(duì)圖片進(jìn)行質(zhì)量壓縮,再上傳服務(wù)器。圖片有三種存在形式:硬盤(pán)上時(shí)是file,網(wǎng)絡(luò)傳輸時(shí)是stream,內(nèi)存中是stream或bitmap,所謂的質(zhì)量壓縮,它其實(shí)只能實(shí)現(xiàn)對(duì)file的影響,你可以把一個(gè)file轉(zhuǎn)成bitmap再轉(zhuǎn)成file,或者直接將一個(gè)bitmap轉(zhuǎn)成file時(shí),這個(gè)最終的file是被壓縮過(guò)的,但是中間的bitmap并沒(méi)有被壓縮。bitmap.compress(Bitmap.CompressFormat.PNG,100,bos);
七、線(xiàn)程優(yōu)化:
使用線(xiàn)程池。為什么要用線(xiàn)程池?
1、從“為每個(gè)任務(wù)分配一個(gè)線(xiàn)程”轉(zhuǎn)換到“在線(xiàn)程池中執(zhí)行任務(wù)”
2、通過(guò)重用現(xiàn)有的線(xiàn)程而不是創(chuàng)建新線(xiàn)程,可以處理多個(gè)請(qǐng)求在創(chuàng)建銷(xiāo)毀過(guò)程中產(chǎn)生的巨大開(kāi)銷(xiāo)
3、當(dāng)使用線(xiàn)程池時(shí),在請(qǐng)求到來(lái)時(shí)間 ,不用等待系統(tǒng)重新創(chuàng)建新的線(xiàn)程,而是直接復(fù)用線(xiàn)程池中的線(xiàn)程,這樣可以提高響應(yīng)性。
4、通過(guò)和適當(dāng)調(diào)整線(xiàn)程池的大小 ,可以創(chuàng)建足夠多的線(xiàn)程以使處理器能夠保持忙碌狀態(tài),同時(shí)還可以防止過(guò)多線(xiàn)程相互競(jìng)爭(zhēng)資源而使應(yīng)用程序耗盡內(nèi)存或者失敗。
5、一個(gè)App里面所有的任務(wù)都放在線(xiàn)程池中執(zhí)行后,可以統(tǒng)一管理 ,當(dāng)應(yīng)用退出時(shí),可以把程序中所有的線(xiàn)程統(tǒng)一關(guān)閉,避免了內(nèi)存和CPU的消耗。
6、如果這個(gè)任務(wù)是一個(gè)循環(huán)調(diào)度任務(wù),你則必須在這個(gè)界面onDetach方法把這個(gè)任務(wù)給cancel掉,如果是一個(gè)普通任務(wù)則可cancel,可不cancel,但是最好cancel
7、整個(gè)APP的總開(kāi)關(guān)會(huì)在應(yīng)用退出的時(shí)間把整個(gè)線(xiàn)程池全部關(guān)閉。
八、一些性能優(yōu)化建議:
1)避免創(chuàng)建過(guò)多對(duì)象,造成頻繁的gc
2)不要過(guò)多使用枚舉,枚舉占用的空間比整型大很多
3)字符串的拼接使用StringBuffer、StringBuilder來(lái)替代直接使用String,因?yàn)槭褂肧tring會(huì)創(chuàng)建多個(gè)String對(duì)象,參考第一條。
4)適當(dāng)使用軟引用,(弱引用就不太推薦了)
5)使用內(nèi)存緩存和磁盤(pán)緩存。
隨著智能手機(jī)的不斷發(fā)展以及用戶(hù)需求的不斷增加,手機(jī)的運(yùn)行內(nèi)存(RAM)的大小已經(jīng)從MB過(guò)渡到了GB容量,作為用戶(hù)的我們只是知道運(yùn)行內(nèi)存越大越好,而運(yùn)行內(nèi)存到底有什么用你知道么?接下來(lái)是我為大家收集的提升Android手機(jī)運(yùn)行內(nèi)存教程,希望能幫到大家。
提升Android手機(jī)運(yùn)行內(nèi)存教程
知識(shí)小科普
無(wú)應(yīng)用運(yùn)行時(shí)內(nèi)存占用已近半
這個(gè)時(shí)候就又到了筆者給大家科普的時(shí)候了。RAM全稱(chēng)Random Access Memory,我們都習(xí)慣稱(chēng)之為運(yùn)行內(nèi)存,又稱(chēng)隨機(jī)存儲(chǔ)器。其是與CPU直接交換數(shù)據(jù)的內(nèi)部存儲(chǔ)器,也叫主存(內(nèi)存)。它可以隨時(shí)讀寫(xiě),并且速度很快,通常作為系統(tǒng)或正在運(yùn)行程序的臨時(shí)數(shù)據(jù)存儲(chǔ)媒介。
為啥安卓手機(jī)更吃?xún)?nèi)存
看到這你可能深深的認(rèn)為RAM還是越大越好,對(duì)沒(méi)錯(cuò)筆者也是這么認(rèn)為的。縱觀安卓手機(jī)的發(fā)展,RAM已經(jīng)從最初的128MB發(fā)展到了現(xiàn)在的6GB(消息稱(chēng)8GB已經(jīng)在路上),而蘋(píng)果從最初的128MB至今RAM也不過(guò)才發(fā)展到2GB而已,但仍然可以流暢運(yùn)行,這又是為何呢?
iOS VS Android(圖片引自antutu)
這就完全要?dú)w結(jié)于安卓和蘋(píng)果不同的內(nèi)存運(yùn)行機(jī)制。安卓系統(tǒng)在運(yùn)行一個(gè)程序時(shí):CPU開(kāi)始計(jì)算-內(nèi)存開(kāi)始緩存-再讀取目標(biāo)文件開(kāi)始計(jì)算,當(dāng)結(jié)束程序時(shí)CPU計(jì)算完畢但內(nèi)存仍然有部分緩存占用。而蘋(píng)果就不同當(dāng)CPU開(kāi)始運(yùn)算后就會(huì)收集所有內(nèi)存為應(yīng)用運(yùn)行進(jìn)行緩存,在結(jié)束應(yīng)用時(shí)會(huì)釋放全部?jī)?nèi)存。
用戶(hù)的內(nèi)存不足解決之道
對(duì)于一般用戶(hù)來(lái)說(shuō)就是安裝各類(lèi)清理軟件,卸載多余不常用APP,軟件關(guān)閉后及時(shí)清理后臺(tái)。目前許多手機(jī)中還加入了后臺(tái)應(yīng)用管理的功能并提供一鍵清理選項(xiàng),實(shí)在受不了的時(shí)候就對(duì)手機(jī)進(jìn)行一次出廠化設(shè)置。
手機(jī)中自帶的權(quán)限管理應(yīng)用
對(duì)于安卓有一定了解的用戶(hù),則會(huì)選擇精簡(jiǎn)版的ROM來(lái)進(jìn)行刷機(jī)(一般情況下系統(tǒng)的精簡(jiǎn)度是和流暢性成正比的),并通過(guò)ROOT獲取權(quán)限,從根本控制軟件的自啟及對(duì)內(nèi)存的占用。
各類(lèi)刷機(jī)軟件中都提供精簡(jiǎn)版ROM一鍵刷機(jī)和一鍵ROOT(圖片引自romjd)
而那些動(dòng)手能力極強(qiáng)的用戶(hù)還會(huì)選擇一些特別的方法,比如通過(guò)創(chuàng)建Swap(交換分區(qū))來(lái)解決,當(dāng)用戶(hù)的實(shí)體內(nèi)存不足時(shí)便會(huì)調(diào)用這部分虛擬內(nèi)存來(lái)運(yùn)行應(yīng)用。
Linux中的Swap即交換分區(qū),類(lèi)似于Windows的虛擬內(nèi)存,就是當(dāng)內(nèi)存不足的時(shí)候,把一部分硬盤(pán)空間虛擬成內(nèi)存使用,從而解決內(nèi)存容量不足的情況。而Android正是基于Linux研發(fā)的操作系統(tǒng),所以也可以使用Swap分區(qū)來(lái)提升系統(tǒng)運(yùn)行效率。
對(duì)于安卓手機(jī)如何創(chuàng)建Swap的具體過(guò)程筆者就不做過(guò)多介紹,不過(guò)首先你的手機(jī)內(nèi)核需要支持Swap,并且已ROOT,可以利用內(nèi)置存儲(chǔ)或內(nèi)存卡(需注意卡片讀寫(xiě)速度)進(jìn)行制作,詳細(xì)方法及所需軟件請(qǐng)執(zhí)行百度。
看了“提升Android手機(jī)運(yùn)行內(nèi)存教程”還想看:
1. 安卓手機(jī)運(yùn)行內(nèi)存不夠用的解決方法
2. 怎樣能刷運(yùn)行內(nèi)存
3. 安卓手機(jī)運(yùn)行內(nèi)存太小怎么優(yōu)化
4. 怎樣擴(kuò)大手機(jī)內(nèi)部?jī)?nèi)存
5. 怎樣擴(kuò)展手機(jī)最大內(nèi)存
內(nèi)容整理自網(wǎng)絡(luò)。
在做內(nèi)存優(yōu)化的時(shí)候,我們發(fā)現(xiàn)除了解決內(nèi)存泄露問(wèn)題,剩下的就只有想辦法減少真實(shí)的內(nèi)存占用。而在App中,大部分內(nèi)存可能被我們圖片占用了,所以減少圖片的內(nèi)存占用可以帶來(lái)直接的效果。本文就簡(jiǎn)單介紹一張圖片到底占用多少內(nèi)存,我們先假設(shè)我們有一張圖片時(shí)** 600 * 800** 的,圖片占用空間大小假設(shè)是** 100KB**。
圖片內(nèi)存大小跟占用空間大小有什么關(guān)系?
占用空間的大小不是圖片占用內(nèi)存的大小,一些初學(xué)者可能會(huì)誤解一下。占用空間是在磁盤(pán)上占用的空間,內(nèi)存大小是加載到內(nèi)存中占用的內(nèi)存大小。兩個(gè)只是單位是一樣的,本質(zhì)不是一個(gè)概念。
一張圖片到底占用多少內(nèi)存呢?(ARGB_8888編碼)
1. 圖片占用內(nèi)存的計(jì)算公式: 圖片高度 * 圖片寬度 * 一個(gè)像素占用的內(nèi)存大小
2. 所以上面的圖片占用內(nèi)存是:**800 * 600 * 4 byte = 1875KB = 1.83M **
上面的計(jì)算公式中,為什么是4byte呢?文章后面有總結(jié)哦
圖片所在目錄對(duì)內(nèi)存的影響?
在Android中,圖片的存放目錄和手機(jī)的屏幕密度影響圖片最終的大小,舉個(gè)例子:
假設(shè)我們的圖片放到 xhdpi 目錄下,那么我們本文中的圖片占用的內(nèi)存大小如下:
屏幕密度為2的設(shè)備:800 * 600 * 4byte = 1.83M
屏幕密度為3的設(shè)備:800 * 1.5 * 600 * 1.5 * 4byte = 1.83 * 2.25M =** 4.12M**
所以,計(jì)算圖片占用內(nèi)存大小的時(shí)候,要考慮圖片所在的目錄跟設(shè)備密度,這兩個(gè)因素其實(shí)影響的是圖片的高寬,android會(huì)對(duì)圖片進(jìn)行拉升跟壓縮。
總結(jié)
1. 圖片確實(shí)很占用內(nèi)存,內(nèi)存優(yōu)化先考慮圖片內(nèi)存占用;
2. 一定要避免使用大圖片,這就是.9圖很有用的原因之一;
3. 圖片的大小對(duì)內(nèi)存的影響是正比關(guān)系;
4. 本文只是簡(jiǎn)單的告知讀者怎么計(jì)算圖片的內(nèi)存大小。
大圖: 440 * 336 ?? 小圖: 220 * 168 資源目錄: xhdpi
小圖的高寬都是大圖的1/2--小圖是原圖的1/4
界面效果:
測(cè)試設(shè)備: Coolpad ? 8676-M01 ? 5.1 ? density=2.0
測(cè)試前準(zhǔn)備操作: 同一款設(shè)備,設(shè)置圖片前后多次調(diào)用gc直到內(nèi)存短時(shí)間內(nèi)保持穩(wěn)定不再變化
內(nèi)存使用情況: 下圖依次是 初始內(nèi)存,大圖內(nèi)存,小圖內(nèi)存
大圖占用內(nèi)存: 11.23 MB - 10.66 MB = 0.57 MB
小圖占用內(nèi)存: 10.81 MB - 10.66 MB = 0.15 MB
大圖小圖內(nèi)存關(guān)系: 0.15 MB * 4 = 0.60 MB 約等于 0.57 MB (這是統(tǒng)計(jì)工具的誤差,理論上就是相等的)
同樣的方式在另外一臺(tái)設(shè)備小米4c上得到的結(jié)果如下:
測(cè)試設(shè)備: Xiaomi ? Mi-4c ? V8.2.1.0.LXKCNDL ? 5.1.1 ? density=3.0
大圖占用內(nèi)存: 13.22 MB - 11.95 MB = 1.27 MB
小圖占用內(nèi)存: 12.27 MB - 11.95 MB = 0.32 MB
大圖小圖內(nèi)存關(guān)系: 0.32 MB * 4 = 1.28 MB 約等于 1.27 MB
結(jié)論: 由此可見(jiàn)大圖比小圖占用更多的內(nèi)存,圖片大?。ǚ直媛剩┡c占用內(nèi)存成正比關(guān)系
備注: 圖片在硬盤(pán)上占用的磁盤(pán)空間大小,與在內(nèi)存中占用的內(nèi)存大小完全不一樣,不是一個(gè)概念,不要混淆
根據(jù)上文中圖片大小與內(nèi)存的關(guān)系,可以更加深刻的理解Android中.9圖片的作用,它不但能減少apk的體積,還能減少圖片占用內(nèi)存。
有些時(shí)候我們根本不需要圖片,而是自己繪制背景,可以在自定義View的onDraw中繪制背景,當(dāng)然最方便的還是使用系統(tǒng)的Drawable,繪制部分交給系統(tǒng)去完成。
下面測(cè)試圖片與Drawable的內(nèi)存占用對(duì)比
原始圖片大?。?482 * 482
界面效果:
測(cè)試設(shè)備: Xiaomi ? Mi-4c ? V8.2.1.0.LXKCNDL ? 5.1.1
測(cè)試前準(zhǔn)備操作: 同一款設(shè)備,設(shè)置背景前后多次調(diào)用gc直到內(nèi)存短時(shí)間內(nèi)保持穩(wěn)定不再變化
內(nèi)存使用情況: 下圖依次是 初始內(nèi)存,使用圖片占用的內(nèi)存,使用Drawable占用的內(nèi)存,使用onDraw繪制占用的內(nèi)存
使用圖片占用內(nèi)存: 13.97 MB - 11.97 MB = 2.00 MB
使用Drawable占用內(nèi)存: 11.97 MB - 11.97 MB = 0.00 MB (不會(huì)是0,有誤差,只是很少)
使用onDraw繪制占用內(nèi)存: 11.98 MB - 11.97 MB = 0.01 MB
結(jié)論: 繪制背景,或者使用系統(tǒng)提供Drawable作為背景,會(huì)大大減少內(nèi)存占用
Drawable參考資料:
Drawable實(shí)戰(zhàn)解析:Android XML shape 標(biāo)簽使用詳解(apk瘦身,減少內(nèi)存好幫手)
Android GradientDrawable(shape標(biāo)簽定義)靜態(tài)使用和動(dòng)態(tài)使用(圓角,漸變實(shí)現(xiàn))
“讓你的圖片最小化”一節(jié)中描述的方法:使用盡可能小的圖,使用.9,自己繪制背景或者使用Drawable來(lái)繪制背景
加載大圖片時(shí)需要對(duì)圖片進(jìn)行壓縮,使用等比例壓縮方法直接在內(nèi)存中處理圖片
這樣做要注意的是,圖片質(zhì)量會(huì)變差,inSampleSize設(shè)置的值越大,圖片質(zhì)量就越差。
有時(shí)候我們?nèi)〉靡粡垐D片,也許只是為了獲得這個(gè)圖片的一些信息,比如圖片的width、height等信息,不需要顯示到界面上,這個(gè)時(shí)候我們可以不把圖片加載到內(nèi)存中。
由于Android外層是使用java,而底層使用的是C語(yǔ)言為圖片對(duì)象分配的內(nèi)存空間。所以我們的外部雖然看起來(lái)釋放了,但里層卻并不一定完全釋放了,我們使用完圖片后最好再釋放掉里層的內(nèi)存空間。
RGB(ARGB)
RGB色彩模式是工業(yè)界的一種顏色標(biāo)準(zhǔn),是通過(guò)對(duì)紅(R)、綠(G)、藍(lán)(B)三個(gè)顏色通道的變化以及它們相互之間的疊加來(lái)得到各式各樣的顏色的,RGB即是代表紅、綠、藍(lán)三個(gè)通道的顏色,這個(gè)標(biāo)準(zhǔn)幾乎包括了人類(lèi)視力所能感知的所有顏色,是目前運(yùn)用最廣的顏色系統(tǒng)之一。在Android中還有包含透明度Alpha的顏色模型,即ARGB。
YUV
YUV,分為三個(gè)分量,“Y”表示明亮度(Luminance或Luma),也就是灰度值;而“U”和“V” 表示的則是色度(Chrominance或Chroma),作用是描述影像色彩及飽和度,用于指定像素的顏色。
YUV的原理是把亮度與色度分離,研究證明,人眼對(duì)亮度的敏感超過(guò)色度。利用這個(gè)原理,可以把色度信息減少一點(diǎn),人眼也無(wú)法查覺(jué)這一點(diǎn)。
主要用于電視系統(tǒng)以及模擬視頻領(lǐng)域,它將亮度信息(Y)與色彩信息(UV)分離,沒(méi)有UV信息一樣可以顯示完整的圖像,只不過(guò)是黑白的,這樣的設(shè)計(jì)很好地解決了彩色電視機(jī)與黑白電視的兼容問(wèn)題
YUV的存儲(chǔ)中與RGB格式最大不同在于,RGB格式每個(gè)點(diǎn)的數(shù)據(jù)是連繼保存在一起的。即R,G,B是前后不間隔的保存在2-4byte空間中。而YUV的數(shù)據(jù)中為了節(jié)約空間,U,V分量空間會(huì)減小。每一個(gè)點(diǎn)的Y分量獨(dú)立保存,但連續(xù)幾個(gè)點(diǎn)的U,V分量是保存在一起的,(反正人眼一般也看不出區(qū)別).這幾個(gè)點(diǎn)合起來(lái)稱(chēng)為macro-pixel, 這種存儲(chǔ)格式稱(chēng)為Packed格式。另外一種存儲(chǔ)格式是把一幅圖像中Y,U,V分別用三個(gè)獨(dú)立的數(shù)組表示。這種模式稱(chēng)為planar模式。
CMYK
??CMYK也稱(chēng)作印刷色彩模式,顧名思義就是用來(lái)印刷的。印刷四分色模式是彩色印刷時(shí)采用的一種套色模式,利用色料的三原色混色原理,加上黑色油墨,共計(jì)四種顏色混合疊加,形成所謂“全彩印刷”。四種標(biāo)準(zhǔn)顏色是:
CMYK和RGB相比有一個(gè)很大的不同:RGB模式是一種發(fā)光的色彩模式,你在一間黑暗的房間內(nèi)仍然可以看見(jiàn)屏幕上的內(nèi)容;CMYK是一種依靠反光的色彩模式,我們是怎樣閱讀報(bào)紙的內(nèi)容呢?是由陽(yáng)光或燈光照射到報(bào)紙上,再反射到我們的眼中,才看到內(nèi)容。它需要有外界光源,如果你在黑暗房間內(nèi)是無(wú)法閱讀報(bào)紙的。只要是在印刷品上看到的圖像,就是CMYK模式表現(xiàn)的。比如期刊、雜志、報(bào)紙、宣傳畫(huà)等,都是印刷出來(lái)的,那么就是CMYK模式的了。
CMYK原色與疊加之后的顏色對(duì)比
在不考慮透明度的情況下,一個(gè)像素點(diǎn)的顏色值在計(jì)算機(jī)中的表示方法有以下3種:
在Java中,float類(lèi)型的變量占32位,int類(lèi)型的變量占32位,short和char類(lèi)型的變量都在16位,因此可以看出,用浮點(diǎn)數(shù)表示法編碼一個(gè)像素的顏色,內(nèi)存占用量是96位即12字節(jié);而用24位整數(shù)表示法編碼,只要一個(gè)int類(lèi)型變量,占用4個(gè)字節(jié)(高8位空著,低24位用于表示顏色);用16位整數(shù)表示法編碼,只要一個(gè)short類(lèi)型變量,占2個(gè)字節(jié);因此可以看出采用整數(shù)表示法編碼顏色值,可以大大節(jié)省內(nèi)存,當(dāng)然,顏色質(zhì)量也會(huì)相對(duì)低一些。在Android中獲取Bitmap的時(shí)候一般也采用整型編碼。
回想一下Android的BitmapConfig類(lèi)中,有ARGB_8888、ARGB_4444、RGB565等常量,現(xiàn)在可以知道它們分別代表了什么含義。同時(shí)也可以計(jì)算一張圖片在內(nèi)存中可能占用的大小,比如采用ARGB_8888編碼載入一張1920 1200的圖片,大概就會(huì)占用1920 1200*4/1024/1024=8.79MB的內(nèi)存。
采用低內(nèi)存占用量的編碼方式,比如Bitmap.Config.ARGB_4444比Bitmap.Config.ARGB_8888更省內(nèi)存;
1920 1200的圖片:*
ARGB_8888:1920 1200 4/1024/1024=8.79MB
ARGB_4444,RGB565:1920 1200 2/1024/1024=4.39MB
在Android中,對(duì)圖片的使用一定要關(guān)注,大多數(shù)情況下,占用內(nèi)存多,OOM發(fā)生都是因?yàn)閳D片資源使用不當(dāng)。不要盲目加一個(gè)大圖到Android項(xiàng)目中,能使用.9進(jìn)來(lái)使用,而且.9圖本身盡可能小,另外能使用繪制實(shí)現(xiàn)就不要加一個(gè)圖片資源。有些時(shí)候,在不影響用戶(hù)體驗(yàn)的情況下,可以降低圖片素材質(zhì)量,比如不需要透明度的就不要了,有些透明度用肉眼看不出來(lái)。
2個(gè)基本原則
既然需要的內(nèi)存公式已得到,那優(yōu)化就顯而易見(jiàn)了,無(wú)非就是減小的這三個(gè)參數(shù)的值,具體的策略如下:
這里我們將圖片分為2種情況來(lái)探討:
圖片占用的內(nèi)存 大小為:
為什么mipmap不在這種情況的考慮范圍之內(nèi)呢?
因?yàn)閙ipmap是Android系統(tǒng)為了避免Launcher Icon變形而添加的資源目錄,也就是說(shuō),mipmap中的圖片不會(huì)被縮放。所以Google也不推薦將除Launcher Icon之外的圖片放在mipmap目錄中。
本地圖片通常都是通過(guò)Android提供的BitmapFactory來(lái)加載的, 這里看幾個(gè)常用的API:
圖片的優(yōu)化可通過(guò)Options參數(shù)來(lái)實(shí)現(xiàn)(Options的介紹可參考 從fresco 看圖片優(yōu)化 :
inPreferredConfig的取值為Bitmap.Config類(lèi)型(這里只考慮以下幾種情況),它是一個(gè)枚舉類(lèi)型,用來(lái)設(shè)置每個(gè)像素需要的字節(jié)數(shù):
1.jpeg和gif
2.webp
3.png8, png24, png32
網(wǎng)絡(luò)圖片通常我們都是使用開(kāi)源庫(kù)進(jìn)行加載, 所以不需要拿到Bitmap再進(jìn)行縮放或裁剪。
這時(shí)可讓后臺(tái)實(shí)現(xiàn)網(wǎng)絡(luò)圖片的裁剪,即:根據(jù)圖片的請(qǐng)求參數(shù)返回合適的尺寸,最大也只需要控件的大小即可。
再大也沒(méi)意義,不僅浪費(fèi)流量,還占用內(nèi)存。
如果你的APP中有很多圖片,那么可對(duì)圖片的寬高根據(jù)設(shè)備的內(nèi)存情況進(jìn)行適當(dāng)?shù)目s?。?/p>
盡量為所有分辨率創(chuàng)建資源 資源匹配分辨率 = 減少不必要的縮放,從而提高UI繪制效率
對(duì)于一個(gè)多圖片的APP來(lái)說(shuō),圖片所占內(nèi)存的優(yōu)化是一項(xiàng)必不可少的工作。
總的來(lái)說(shuō),其優(yōu)化也就是通過(guò) 縮放 和指定 Bitmap.Config的值 來(lái)實(shí)現(xiàn)的,只是不同位置,不同格式的圖片有所差異而已。
;utm_source=weixinqun
Android內(nèi)存優(yōu)化一:java垃圾回收機(jī)制
Android內(nèi)存優(yōu)化二:內(nèi)存泄漏
Android內(nèi)存優(yōu)化三:內(nèi)存泄漏檢測(cè)與監(jiān)控
Android內(nèi)存優(yōu)化四:OOM
Android內(nèi)存優(yōu)化五:Bitmap優(yōu)化
壓縮比:scale = (flaot) targetDensity / density
targetDensity : 設(shè)備屏幕像素密度dpi
density: 圖片對(duì)應(yīng)的文件夾的像素密度dpi
1)、同一張圖片放在不同的資源目錄下,其分辨率會(huì)有變化。
2)、Bitmap的分辨率越高,其解析后的寬高越小,甚至小于原有的圖片(及縮放),從而內(nèi)存也響應(yīng)的減少。
3)、圖片不放置任何資源目錄時(shí),其使用默認(rèn)分辨率mdpi:160。
4)、資源目錄分辨率和屏幕分辨率一致時(shí),圖片尺寸不會(huì)縮放。
Bitmap放在資源目錄中的計(jì)算方式為:
主要通過(guò)編碼、采樣、復(fù)用、匿名共享區(qū)進(jìn)行優(yōu)化
由于ARGB_4444的畫(huà)質(zhì)慘不忍睹,一般假如對(duì)圖片沒(méi)有透明度要求的話(huà),可以改成RGB_565,相比ARGB_8888將節(jié)省一半的內(nèi)存開(kāi)銷(xiāo)
其中,A代表透明度;R代表紅色;G代表綠色;B代表藍(lán)色。
ALPHA_8 表示8位Alpha位圖,即A=8,一個(gè)像素點(diǎn)占用1個(gè)字節(jié),它沒(méi)有顏色,只有透明度。
ARGB_4444 表示16位ARGB位圖,即A=4,R=4,G=4,B=4,一個(gè)像素點(diǎn)占4+4+4+4=16位,2個(gè)字節(jié)。
ARGB_8888 表示32位ARGB位圖,即A=8,R=8,G=8,B=8,一個(gè)像素點(diǎn)占8+8+8+8=32位,4個(gè)字節(jié)。
RGB_565 表示16位RGB位圖,即R=5,G=6,B=5,它沒(méi)有透明度,一個(gè)像素點(diǎn)占5+6+5=16位,2個(gè)字節(jié)。
bitmap的占用內(nèi)存,是以bitmap的寬高和每個(gè)像素占用的字節(jié)數(shù)決定的。
根據(jù)BitmapFactory 的采樣率進(jìn)行壓縮 設(shè)置采樣率,不能小于1 假如是2 則寬為之前的1/2,高為之前的1/2,一共縮小1/4 以此類(lèi)推
圖片復(fù)用指的是inBitmap這個(gè)屬性。
不使用這個(gè)屬性,你加載三張圖片,系統(tǒng)會(huì)給你分配三份內(nèi)存空間,用于分別儲(chǔ)存這三張圖片
如果用了inBitmap這個(gè)屬性,加載三張圖片,這三張圖片會(huì)指向同一塊內(nèi)存,而不用開(kāi)辟三塊內(nèi)存空間。
inBitmap的限制:
1、3.0-4.3
復(fù)用的圖片大小必須相同
編碼必須相同
2、4.4以上
復(fù)用的空間大于等于即可
編碼不必相同
3、不支持WebP
4、圖片復(fù)用,這個(gè)屬性必須設(shè)置為true;
options.inMutable = true;
Android 系統(tǒng)為了進(jìn)程間共享數(shù)據(jù)開(kāi)辟的一塊內(nèi)存區(qū)域,由于這塊區(qū)域不受應(yīng)用的Head的大小限制,相當(dāng)于可以繞開(kāi)oom,F(xiàn)aceBook的Fresco首次應(yīng)用到實(shí)際中。
限制:5.0以后就限制了匿名共享內(nèi)存的使用。
在SDK 11 - 18之間,重用的bitmap大小必須是一致的,例如給inBitmap賦值的圖片大小為100-100,那么新申請(qǐng)的bitmap必須也為100-100才能夠被重用。從SDK 19開(kāi)始,新申請(qǐng)的bitmap大小必須小于或者等于已經(jīng)賦值過(guò)的bitmap大小。 新申請(qǐng)的bitmap與舊的bitmap必須有相同的解碼格式,例如大家都是8888的,如果前面的bitmap是8888,那么就不能支持4444與565格式的bitmap了。 我們可以創(chuàng)建一個(gè)包含多種典型可重用bitmap的對(duì)象池,這樣后續(xù)的bitmap創(chuàng)建都能夠找到合適的“模板”去進(jìn)行重用。
8.0Bitmap的像素?cái)?shù)據(jù)存儲(chǔ)在Native,為什么又改為Native存儲(chǔ)呢?
因?yàn)?.0共享了整個(gè)系統(tǒng)的內(nèi)存,測(cè)試8.0手機(jī)如果一直創(chuàng)建Bitmap,如果手機(jī)內(nèi)存有1G,那么你的應(yīng)用加載1G也不會(huì)oom。
可以利用LRU開(kāi)管理Bitmap,給他設(shè)置內(nèi)存最大值,及時(shí)回收。
BitmapRegionDecoder
Android內(nèi)存優(yōu)化一:java垃圾回收機(jī)制
Android內(nèi)存優(yōu)化二:內(nèi)存泄漏
Android內(nèi)存優(yōu)化三:內(nèi)存泄漏檢測(cè)與監(jiān)控
Android內(nèi)存優(yōu)化四:OOM
Android內(nèi)存優(yōu)化五:Bitmap優(yōu)化
Memory Profiler 是 Profiler 中的其中一個(gè)版塊,Profiler 是 Android Studio 為我們提供的性能分析工具,使用 Profiler 能分析應(yīng)用的 CPU、內(nèi)存、網(wǎng)絡(luò)以及電量的使用情況。
進(jìn)入了 Memory Profiler 界面。
點(diǎn)擊 Record 按鈕后,Profiler 會(huì)為我們記錄一段時(shí)間內(nèi)的內(nèi)存分配情況。
在內(nèi)存分配面板中,通過(guò)拖動(dòng)時(shí)間線(xiàn)來(lái)查看一段時(shí)間內(nèi)的內(nèi)存分配情況
通過(guò)搜索類(lèi)或者報(bào)名的方式查看對(duì)象的使用情況
使用Memory Profiler 分析內(nèi)存可以查看官網(wǎng): 使用內(nèi)存性能分析器查看應(yīng)用的內(nèi)存使用情況
對(duì)于內(nèi)存泄漏問(wèn)題,Memory Profiler 只能提供一個(gè)簡(jiǎn)單的分析,不能夠確認(rèn)具體發(fā)生問(wèn)題的地方。
而 MAT 就可以幫我們做到這一點(diǎn),它是一款功能強(qiáng)大的 Java 堆內(nèi)存分析工具,可以用于查找內(nèi)存泄漏以及查看內(nèi)存消耗情況。
as 生成hprof文件無(wú)法被mat識(shí)別,需要進(jìn)行轉(zhuǎn)換
使用hprof-conv進(jìn)行轉(zhuǎn)換,hprof-conv位于sdk\platform-tools
ps:as導(dǎo)出hprof前最好先gc幾次,可排除一些干擾
Histogram 可以列出內(nèi)存中的對(duì)象,對(duì)象的個(gè)數(shù)以及大??; Dominator Tree 可以列出那個(gè)線(xiàn)程,以及線(xiàn)程下面的那些對(duì)象占用的空間; Top consumers 通過(guò)圖形列出最大的object; Leak Suspects 通過(guò)MA自動(dòng)分析泄漏的原因。
Shallow Heap就是對(duì)象本身占用內(nèi)存的大小,不包含其引用的對(duì)象內(nèi)存,實(shí)際分析中作用不大。常規(guī)對(duì)象(非數(shù)組)的ShallowSize由其成員變量的數(shù)量和類(lèi)型決定。數(shù)組的shallow size有數(shù)組元素的類(lèi)型(對(duì)象類(lèi)型、基本類(lèi)型)和數(shù)組長(zhǎng)度決定。對(duì)象成員都是些引用,真正的內(nèi)存都在堆上,看起來(lái)是一堆原生的byte[], char[], int[],對(duì)象本身的內(nèi)存都很小。
Retained Heap值的計(jì)算方式是將Retained Set(當(dāng)該對(duì)象被回收時(shí)那些將被GC回收的對(duì)象集合)中的所有對(duì)象大小疊加。或者說(shuō),因?yàn)閄被釋放,導(dǎo)致其它所有被釋放對(duì)象(包括被遞歸釋放的)所占的heap大小。
Path To GC Roots - exclude all phantim/weak/soft etc. references:查看這個(gè)對(duì)象的GC Root,不包含虛、弱引用、軟引用,剩下的就是強(qiáng)引用。從GC上說(shuō),除了強(qiáng)引用外,其他的引用在JVM需要的情況下是都可以 被GC掉的,如果一個(gè)對(duì)象始終無(wú)法被GC,就是因?yàn)閺?qiáng)引用的存在,從而導(dǎo)致在GC的過(guò)程中一直得不到回收,因此就內(nèi)存泄漏了。
List objects - with incoming references:查看這個(gè)對(duì)象持有的外部對(duì)象引用
List objects - with outcoming references:查看這個(gè)對(duì)象被哪些外部對(duì)象引用
使用對(duì)象查詢(xún)語(yǔ)言可以快速定位發(fā)生泄漏的Activity及Fragment
使用 MAT 來(lái)分析內(nèi)存問(wèn)題,效率比較低,為了能迅速發(fā)現(xiàn)內(nèi)存泄漏,Square 公司基于 MAT 開(kāi)源了 LeakCanary ,LeakCanary 是一個(gè)內(nèi)存泄漏檢測(cè)框架。
集成LeakCanary后,可以在桌面看到 LeakCanary 用于分析內(nèi)存泄漏的應(yīng)用。
當(dāng)發(fā)生泄漏,會(huì)為我們生成一個(gè)泄漏信息概覽頁(yè),可以看到泄漏引用鏈的詳情。
LeakCanary 會(huì)解析 hprof 文件,并且找出導(dǎo)致 GC 無(wú)法回收實(shí)例的引用鏈,這也就是泄漏蹤跡(Leak Trace)。
泄漏蹤跡也叫最短強(qiáng)引用路徑,這個(gè)路徑是 GC Roots 到實(shí)例的路徑。
LeakCanary 存在幾個(gè)問(wèn)題,不同用于線(xiàn)上監(jiān)控功能
線(xiàn)上監(jiān)控需要做的,就是解決以上幾個(gè)問(wèn)題。
各大廠都有開(kāi)發(fā)線(xiàn)上監(jiān)控方案,比如快手的 KOOM ,美團(tuán)的 Probe ,字節(jié)的 Liko
快手自研OOM解決方案KOOM今日宣布開(kāi)源
總結(jié)一下幾點(diǎn):
通過(guò)無(wú)性能損耗的 內(nèi)存閾值監(jiān)控 來(lái)觸發(fā)鏡像采集。將對(duì)象是否泄漏的判斷延遲到了解析時(shí)
利用系統(tǒng)內(nèi)核COW( Copy-on-write ,寫(xiě)時(shí)復(fù)制)機(jī)制,每次dump內(nèi)存鏡像前先暫停虛擬機(jī),然后fork子進(jìn)程來(lái)執(zhí)行dump操作,父進(jìn)程在fork成功后立刻恢復(fù)虛擬機(jī)運(yùn)行,整個(gè)過(guò)程對(duì)于父進(jìn)程來(lái)講總耗時(shí)只有幾毫秒,對(duì)用戶(hù)完全沒(méi)有影響。
本文名稱(chēng):android內(nèi)存優(yōu)化,android內(nèi)存優(yōu)化工具
網(wǎng)站地址:http://jinyejixie.com/article30/hojsso.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供用戶(hù)體驗(yàn)、網(wǎng)站制作、域名注冊(cè)、全網(wǎng)營(yíng)銷(xiāo)推廣、網(wǎng)站建設(shè)、響應(yīng)式網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
移動(dòng)網(wǎng)站建設(shè)知識(shí)