android圖片的優化
Ⅰ Android性能優化-大解析度圖片最佳實踐
好久沒更新博客了,借著908公司18周年年會這個普(期)天(待)同(紅)慶(包)的日子,來說下安卓中的圖片與內存的關系。
大家都知道安卓中圖片是佔用內存的大戶,在日常開發中也免不了用到圖片,那麼圖片佔用內存與哪些因素有關呢,先直接給結論:
1)與圖片解析度有關;
2)與開發者放的文件目錄有關;
3)與圖片大小沒有半毛錢關系。
舉個例子:
以現在主流1080p手機為例,新建一個空的工程,用一張1080*1080像素圖片來測試:
將圖片放在xxhdpi目錄下,測試內存,效果如下:
大家可以接著嘗試將圖片放到mhdpi目錄 或者xhdpi目錄下,看下內存佔用情況,上面放xxhdpi從圖上看大概佔4M左右,那麼這個值是怎麼計算來的:
放xxhpi下圖片內存佔用 = 1080 *1080 *4 /1024 / 1024 = 4.45M
稍微解釋下公式,像素長*寬*一個像素佔用的位元組數,安卓的色彩模式一個像素佔用的位元組關系如下表:
也就是說,你在布局文件里隨便定義一個imageview,載入一個1080*1080的圖片,顯示的時候,將按一像素4byte計算內存占拆配昌用。
如果你按照上面的步驟嘗試了將圖片放到mdpi目錄或者xhdpi目錄,應該知道結論了,圖片佔用內存成倍數的變大了,看下放mdpi文件夾下的效果:
如果開發者將同樣一張1080*1080像素圖片放到mdpi目錄下,圖片佔用內存=(1080*3)*(1080*3)*4 /1024 /1024 = 40M,比之前放xxdpi目錄下內存高出了9倍,所以:圖片不是亂放的,要謹慎。
現在主流手機解析度1080p以上,建議大圖統一放到xxhdpi目錄下管理。
高解析度圖片常見的導致性能缺陷的場景包括:
1)放錯圖片目錄賣基,導致佔用內存成倍數增長;
2)限定了高寬的imageview組件,載入了超過該尺寸大小的圖片;
3)單色值圖片、loading過渡圖片、對清晰度要求不高的圖片等,強上了大解析度圖片。
這些場景都是在實際開發中遇到過的問題,可能出於設計師的疏忽,可能出於程序猿的隨意,修復這些缺陷的成本很低,但是對內存降低的幫助是指數級的,投入產出比這么高的事情,只能說到這里了。
對應的修復手段很明確了:
1)建議圖片放xxhpdi目錄;
2)限定高寬的imageview,圖片最大尺寸不超過該imageview最大承載高寬;
3)簡單圖片直接下掉,或者壓縮下吧,也可以結合業務背景用背景色等替換。
如果你的項目比較小,人肉去找都可以知道哪些是大分旅扒辨率圖片,那麼檢查下使用是否正確。如果你的項目是一個大型客戶端項目,人工去找就很尷尬了,是的,我想說python大法好,來個腳本吧,無死角搞定所有大解析度圖片可能導致的性能缺陷:
Ⅱ 在Android開發中,有哪些好的內存優化方式
我的做法是時間換空間,盡量文件化一些佔用內存的數據。最典型的就是ListView中的Bitmap,可以參考這個開源組件的實現。 其將Bitmap都本地文件緩存,內存中只保留最近使用的4張圖片,在使用中發現還是會偶爾出現OOM,然後我就將其改為完全的讀取文件,內存中不保留圖片,使用以後都自動回收,由此擴展的數據文件也同樣緩存成文件。
除了Bitmap,其他的地方沒想到什麼能佔用這么大內存,網路下載下來的數據文件?需要都留在內存中嗎?目前我做的應用,每次請求的數據大小都比較小,每次Http請求下來的數據都把url轉換成文件名,然後緩存成文件,在下次Http請求的時候先根據url來預讀文件,暫時不用的數據就釋放掉。
經常會OOM我覺得就是在Bitmap處理的時候,比如decodeFile,在往界面上載入圖片時,不用直接載入原圖,可以進行縮放。一張1000*1000的圖片要載入到一個100*100的ImageView上,直接載入進來大多數都會OOM,可以先用inJustDecodeBounds
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
拿到這個圖片的大小,再算好縮放比例
int scale = 0;
scale = (int)(options.outHeight / (float)size);
if (scale <= 0) {
scale = 1;
}
options.inSampleSize = scale;
options.inJustDecodeBounds = false;
再進行decode。
總之就是盡量時間換空間,實際這個時間是非常非常短的,用戶體驗內的。
Ⅲ Android性能優化(八)--Android圖片內存優化
2個基本原則
既然需要的內存公式已得到,那優化就顯而易見了,無非就是減小的這三個參數的值,具體的策略如下:
這里我們將圖片分為2種情況來探討:
圖片佔用的內存 大小為:
為什麼mipmap不在這種情況的考慮范圍之內呢?
因為mipmap是Android系統為了避免Launcher Icon變形而添加的資源目錄,也就是說,mipmap中的圖片不會被縮放。所以Google也不推薦將除Launcher Icon之外的圖片放在mipmap目錄中。
本地圖片通常都是通過Android提供的BitmapFactory來載入的, 這里看幾個常用的API:
圖片的優化可通過Options參數來實現(Options的介紹可參考 從fresco 看圖片優化 :
inPreferredConfig的取值為Bitmap.Config類型(這里只考慮以下幾種情況),它是一個枚舉類型,用來設置每個像素需要的位元組數:
1.jpeg和gif
2.webp
3.png8, png24, png32
網路圖片通常我們都是使用開源庫進行載入, 所以不需要拿到Bitmap再進行縮放或裁剪。
這時可讓後台實現網路圖片的裁剪,即:根據圖片的請求參數返回合適的尺寸,最大也只需要控制項的大小即可。
再大也沒意義,不僅浪費流量,還佔用內存。
如果你的APP中有很多圖片,那麼可對圖片的寬高根據設備的內存情況進行適當的縮小:
盡量為所有解析度創建資源 資源匹配解析度 = 減少不必要的縮放,從而提高UI繪制效率
對於一個多圖片的APP來說,圖片所佔內存的優化是一項必不可少的工作。
總的來說,其優化也就是通過 縮放 和指定 Bitmap.Config的值 來實現的,只是不同位置,不同格式的圖片有所差異而已。
https://juejin.im/post/5af84f4b51882542714fdaa9?utm_medium=an&utm_source=weixinqun
Ⅳ Android圖片載入及虛化效果
[TOC]
使用如下方式載入圖片
會導致OOM,android對於直接通過資源id載入的資源需做cache,下次再需要此資源的時候直接從cache中得到。但這樣做也造成了用過的資源都會在內存中,這樣的設計不是很適合使用了很多大圖片資源的應用,這樣累積下來應用的內存峰值是很高的。
當使用諸如
imageView.setBackgroundResource
imageView.setImageResource
BitmapFactory.decodeResource
這樣的方法來設置一張大圖片時,在完成decode後,最終都是通過java層的createBitmap來完成的,需要消耗更多內存。因此,改用先通過BitmapFactory.decodeStream方法,創建出一個bitmap,再將其設為ImageView的 source,decodeStream最大的秘密在於其直接調用JNI>>nativeDecodeAsset()來完成decode,無需再使用java層的createBitmap,從而節省了java層的空間。如果在讀取時加上圖片的Config參數,可以有效減少載入的內存,從而有效阻止拋OOM異常。
實際使用中,可以針對bitmap做如下操作
RenderScript是Google在API11中引入的類,可看作業android內置的圖片處理框架(區別於Glide等圖片處理框架,RenderScript注重於圖片的處理而不是載入)。RenderScript實際操作基於RenderScript Intrinsics,一些可以幫助RenderScript快速實現各種圖片處理的操作類。該類包含諸多操作功能,比如利用ScriptIntrinsicBlur,就可以簡單高效地實現高斯模糊效果,可通過參數radius設置虛化的程度。
1920*1080的原始圖片未經壓縮讀取時間可能會超過1s,使用該圖片作為背景圖片載入時會有明顯的卡頓。此時就需要設置BitmapFactory.Options實現對待載入圖片的壓縮。可參照 https://blog.csdn.net/u012124438/article/details/66087785 逐步優化Bitmap載入。對於載入圖片較多較頻繁的功能,建議使用第三方的圖片載入框架,如Glide或者Picasso。
需要注意的是,此處doBlur有兩個重載,可根據需要設置圖片的縮放比例.這種方式和前文通過BitmapFactory.Options設置Bitmap取樣格式的效果是一致的,都是為了減小Bitmap載入的資源消耗,提高載入效率。
Ⅳ Android性能優化總結
常用的Android性能優化方法:
一、布局優化:
1)盡量減少布局文件的層級。
層級少了,繪制的工作量也就少了,性能自然提高。
2)布局重用 <include標簽>
3)按需載入:使用ViewStub,它繼承自View,一種輕量級控制項,本身不參與任何的布局和繪制過程。他的layout參數里添加一個替換的布局文件,當它通過setVisibility或者inflate方法載入後,它就會被內部布局替換掉。
二、繪制優化:
基於onDraw會被調用多次,該方法內要避免兩類操作:
1)創建新的局部對象,導致大量垃圾對象的產生,從而導致頻繁的gc,降低程序的執行效率。
2)不要做耗時操作,搶CPU時間片,造成繪制很卡不流暢。
三、內存泄漏優化:
1)靜態變數導致內存泄漏 比較明顯
2)單例模式導致的內存泄漏 單例無法被垃圾回收,它持有的任何對象的引用都會導致該對象不會被gc。
3)屬性動畫導致內存泄漏 無限循環動畫,在activity中播放,但是onDestroy時沒有停止的話,動畫會一直播放下去,view被動畫持有,activity又被view持有,導致activity無法被回收。
四、響應速度優化:
1)避免在主線程做耗時操作 包括四大組件,因為四大組件都是運行在主線程的。
2)把一些創建大量對象等的初始化工作放在頁面回到前台之後,而不應該放到創建的時候。
五、ListView的優化:
1)使用convertView,走listView子View回收的一套:RecycleBin 機制
主要是維護了兩個數組,一個是mActiveViews,當前可見的view,一個是mScrapViews,當前不可見的view。當觸摸ListView並向上滑動時,ListView上部的一些OnScreen的View位置上移,並移除了ListView的屏幕范圍,此時這些OnScreen的View就變得不可見了,不可見的View叫做OffScreen的View,即這些View已經不在屏幕可見范圍內了,也可以叫做ScrapView,Scrap表示廢棄的意思,ScrapView的意思是這些OffScreen的View不再處於可以交互的Active狀態了。ListView會把那些ScrapView(即OffScreen的View)刪除,這樣就不用繪制這些本來就不可見的View了,同時,ListView會把這些刪除的ScrapView放入到RecycleBin中存起來,就像把暫時無用的資源放到回收站一樣。
當ListView的底部需要顯示新的View的時候,會從RecycleBin中取出一個ScrapView,將其作為convertView參數傳遞給Adapter的getView方法,從而達到View復用的目的,這樣就不必在Adapter的getView方法中執行LayoutInflater.inflate()方法了。
RecycleBin中有兩個重要的View數組,分別是mActiveViews和mScrapViews。這兩個數組中所存儲的View都是用來復用的,只不過mActiveViews中存儲的是OnScreen的View,這些View很有可能被直接復用;而mScrapViews中存儲的是OffScreen的View,這些View主要是用來間接復用的。
2)使用ViewHolder避免重復地findViewById
3)快速滑動不適合做大量非同步任務,結合滑動監聽,等滑動結束之後載入當前顯示在屏幕范圍的內容。
4)getView中避免做耗時操作,主要針對圖片:ImageLoader來處理(原理:三級緩存)
5)對於一個列表,如果刷新數據只是某一個item的數據,可以使用局部刷新,在列表數據量比較大的情況下,節省不少性能開銷。
六、Bitmap優化:
1)減少內存開支:圖片過大,超過控制項需要的大小的情況下,不要直接載入原圖,而是對圖片進行尺寸壓縮,方式是BitmapFactroy.Options 采樣,inSampleSize 轉成需要的尺寸的圖片。
2)減少流量開銷:對圖片進行質量壓縮,再上傳伺服器。圖片有三種存在形式:硬碟上時是file,網路傳輸時是stream,內存中是stream或bitmap,所謂的質量壓縮,它其實只能實現對file的影響,你可以把一個file轉成bitmap再轉成file,或者直接將一個bitmap轉成file時,這個最終的file是被壓縮過的,但是中間的bitmap並沒有被壓縮。bitmap.compress(Bitmap.CompressFormat.PNG,100,bos);
七、線程優化:
使用線程池。為什麼要用線程池?
1、從「為每個任務分配一個線程」轉換到「在線程池中執行任務」
2、通過重用現有的線程而不是創建新線程,可以處理多個請求在創建銷毀過程中產生的巨大開銷
3、當使用線程池時,在請求到來時間 ,不用等待系統重新創建新的線程,而是直接復用線程池中的線程,這樣可以提高響應性。
4、通過和適當調整線程池的大小 ,可以創建足夠多的線程以使處理器能夠保持忙碌狀態,同時還可以防止過多線程相互競爭資源而使應用程序耗盡內存或者失敗。
5、一個App裡面所有的任務都放在線程池中執行後,可以統一管理 ,當應用退出時,可以把程序中所有的線程統一關閉,避免了內存和CPU的消耗。
6、如果這個任務是一個循環調度任務,你則必須在這個界面onDetach方法把這個任務給cancel掉,如果是一個普通任務則可cancel,可不cancel,但是最好cancel
7、整個APP的總開關會在應用退出的時間把整個線程池全部關閉。
八、一些性能優化建議:
1)避免創建過多對象,造成頻繁的gc
2)不要過多使用枚舉,枚舉佔用的空間比整型大很多
3)字元串的拼接使用StringBuffer、StringBuilder來替代直接使用String,因為使用String會創建多個String對象,參考第一條。
4)適當使用軟引用,(弱引用就不太推薦了)
5)使用內存緩存和磁碟緩存。
Ⅵ Android圖片壓縮與優化的幾種方式
1.使用的圖片最好用png格式
2.如果你的圖片仍然大的話可以在項目裡面點擊右鍵選擇convert to Webp,轉成webp格式圖片可以變小很多!
Ⅶ android 中圖片太大,導致載入特別慢怎麼辦
圖片不會太大,如果載入過慢或載入不出來可能是以下問題:
手機裝的軟體過多,儲存空間不足
網速過慢
手機本身配置落後
可以嘗試長按圖片,然後保存到手機,在相冊中查看
請採納,謝謝