介紹
Android開發應用過程中加載bitmap是很tricky的,如果你稍微不注意,bitmaps就會快速消耗光應用的可用內存,導致應用奔潰,拋出OutofMemoryError異常,俗稱OOM:
java.lang.OutofMemoryError: bitmap size exceeds VM budget.
而這主要有幾個原因:
- Android設備給每個應用分配的可用內存為16M,但是這個值因機型而異(下面有獲取分配內存大小的方法),現在的很多機子分配的limit都高出很多了,對于應用來說,要將使用的內存控制在這個limit以內.
- Bitmap會占用大量內存尤其是照片,比如5百萬像素的攝像頭拍的照片大小為2592x1936 pixels, 如果bitmap的配置使用ARGB_8888(Android 2.3以后的默認值),那么加載一張照片就占用了將近19M的內存(2592*1936*4 bytes),瞬間就將應用的內存limit消耗光了,特別是內存limit較小的設備.
- Android應用的一些UI組件經常需要一次性加載多張bitmaps,比如ListView,GridView和ViewPager.
官網提供的五個教學課程來加載Bitmap
- Loading Large Bitmaps Efficiently
- Processing Bitmaps Off the UI Thread
- Caching Bitmaps
- Managing Bitmap Memory
- Displaying Bitmaps in Your UI
Bitmap.Config的具體配置如下表:
Bitmap.Config | Description |
---|---|
ALPHA_8 | Each pixel is stored as a single translucency (alpha) channel |
ARGB_4444 | This field was deprecated in API level 13. Because of the poor quality of this configuration, it is advised to use ARGB_8888 instead. |
ARGB_8888 | Each pixel is stored on 4 bytes. |
RGB_565 | Each pixel is stored on 2 bytes and only the RGB channels are encoded: red is stored with 5 bits of precision (32 possible values), green is stored with 6 bits of precision (64 possible values) and blue is stored with 5 bits of precision. |
獲取應用分配的最大內存大小的方法:
- Runtime的maxMemory()方法返回bytes
- ActivityManager的getMemoryClass()方法返回megabytes
例:
// get max memory by runtime
long maxBytes=Runtime.getRuntime().maxMemory();
Log.i("Log","maxMemory: "+maxBytes/1024/1024+" M");
// get max memory by activity manager
ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
int maxMemory = activityManager.getMemoryClass();
Log.i("Log","memClass: "+maxMemory+" M");
結果輸出:
Log: maxMemory: 256 M
Log: memClass: 256 M