Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android顯示圖片避免OOM和ANR小結

Android顯示圖片避免OOM和ANR小結

編輯:關於Android編程

    看完了文檔裡關於圖片介紹的幾篇文章,結合項目和一些網上的文章,談下在android平台顯示圖片的一些個人想法。

 

1.從設計角度,最好不要讓手機顯示大於手機屏幕數倍的大圖片,如果源圖是個大圖,加載時把圖片縮小到屏幕大小,使用在decode圖片時使用option選項,直接加載縮小後的圖片。網上不少人說先讀取圖片InputStream流,再通過BitmapFactory.decodeStream(InputStream is)加載速度會快些,我看了api level 14的代碼實現,無論調用哪個decode方法,最後都是調用的這個方法。電腦上沒低版本的源碼,不確定低版本是不是也是這樣實現。

 

2.加載一張圖片,無論是為控件設背景圖還是顯示一張圖片,如果圖片源不是在內存中的,最好不要直接在UI線程中加載它,推薦使用AsyncTask異步加載圖片。原因很簡單,在UI線程加載圖片,加載期間會阻塞UI線程,如果加載圖片時間太長了,會產生ANR問題。

這裡有個疑惑,如果圖片是資源文件,要不要使用異步加載?我認為資源文件沒有必要使用異步加載。通常使用的方法有BitmapFactory.decodeResource(Resource res, int id, Options opts) 或者 setBackgroundResource(int resid)。他們最終都是通過AssetManager.openNonAsset(int cookie, String fileName, int accessMode)獲取一個InputStream,而這個方法是個native方法,沒有去讀它的native實現,但android引入資源文件這一機制,而這一機制並沒有為寫代碼時帶來太多幫助,那麼它應該是文件加載優化的產物。

 

3.對於緩存,文檔建議不要超過初始分配內存的1/8。我覺得這個不要濫用,因為不需要緩存的,你緩存了,白白被消耗一部分內存。也不要拘泥於這個百分比,因為在android中圖片是消耗內存的大戶,普通手機1/8的初始內存,還緩存不了兩張全屏的大圖,命中率太低了還不如不用緩存。對於需要大量顯示圖片的應用或模塊,你內存不給它用,還留著干什麼。

 

4.謹防超大屏幕。對於超大屏,顯示圖片消耗的內存是驚人的,所以你的應用在顯示圖片時,要提醒自己它有可能應用到超大屏的手機上。如果一個activity中需要持有幾個大圖(或者源為小圖,但需要被拉伸為大圖)的引用,一定要記得在activity銷毀時,單獨釋放圖片的內存,因為你退出activity,通常系統並不會銷毀它,所以它持有的引用也會保留。如果需要幾張大圖疊加實現某種效果,最好單獨加載每張圖片,把它畫到一張畫布上,把原來的圖片釋放。這樣的話,最終只消耗一張圖片大小的內存。

自己開發中遇到過一個case: 有幾款手機,在進入某個activity時很容易crash,我檢查了代碼,沒有什麼錯誤。實現的功能就是顯示一個普通的全屏場景,場景是由幾張圖疊加出來的,一張背景,一張草地等等,UI基本是加載layout.xml實現,在代碼中僅僅對UI做了少量微調。分析下內存發現,一進入這個activity,堆內存就增加35M左右,而且退出activity後,這些內存並沒有減少。之前覺得不合理,後來發現手機竟然是1960x1080的分辨率,一張全屏的圖片大小差不多要消耗8M內存,這一堆圖加起來如果有3張全屏圖大小,就得24M內存,再加上一些動畫和其它緩存,占三十多兆也不足為怪了。最後解決辦法是分別加載每張圖片,畫到一張上面,釋放原來的內存。在activity結束後,把圖片內存釋放。測試結果是,這樣優化後,不僅解決了crash,整個應用速度也流暢不少。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved