<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 8.2.2 Bitmap引起的OOM問題 ## 本節引言: > 上節,我們已經學習了Bitmap的基本用法,而本節我們要來探討的Bitmap的OOM問題, 大家在實際開發中可能遇到過,或者沒遇到過因為Bitmap引起的OOM問題,本節我們 就來圍繞這個話題來進行學習~了解什么是OOM,為什么會引起OOM,改善因Bitmap引起的 OOM問題~ ## 1.什么是OOM?為什么會引起OOM? 答:**Out Of Memory**(內存溢出),我們都知道Android系統會為每個APP分配一個獨立的工作空間, 或者說分配一個單獨的Dalvik虛擬機,這樣每個APP都可以獨立運行而不相互影響!而Android對于每個 Dalvik虛擬機都會有一個最大內存限制,如果當前占用的內存加上我們申請的內存資源超過了這個限制 ,系統就會拋出OOM錯誤!另外,這里別和RAM混淆了,即時當前RAM中剩余的內存有1G多,但是OOM還是會發生!別把RAM(物理內存)和OOM扯到一起!另外RAM不足的話,就是殺應用了,而不是僅僅是OOM了! 而這個Dalvik中的最大內存標準,不同的機型是不一樣的,可以調用: ``` ActivityManager activityManager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE); Log.e("HEHE","最大內存:" + activityManager.getMemoryClass()); ``` 獲得正常的最大內存標準,又或者直接在命令行鍵入: ``` adb shell getprop | grep dalvik.vm.heapgrowthlimit ``` 你也可以打開系統源碼/system/build.prop文件,看下文件中這一部分的信息得出: ``` dalvik.vm.heapstartsize=8m dalvik.vm.heapgrowthlimit=192m dalvik.vm.heapsize=512m dalvik.vm.heaptargetutilization=0.75 dalvik.vm.heapminfree=2m dalvik.vm.heapmaxfree=8m ``` 我們關注的地方有三個:heapstartsize堆內存的初始大小,heapgrowthlimit標準的應用的最大堆 內存大小,heapsize則是設置了使用android:largeHeap的應用的最大堆內存大小! 我這里試了下手頭幾個機型的正常最大內存分配標準: ![](http://www.runoob.com/wp-content/uploads/2015/10/50717226.jpg) 你也可以試試自己手頭的機子~ 好啦,不扯了,關于OOM問題的產生,就扯到這里,再扯就到內存管理那一塊了,可是個大塊頭, 現在還啃不動...下面我們來看下避免Bitmap OOM的一些技巧吧! ## 2.避免Bitmap引起的OOM技巧小結 ### 1)采用低內存占用量的編碼方式 上一節說了**BitmapFactory.Options**這個類,我們可以設置下其中的inPreferredConfig屬性, 默認是**Bitmap.Config.ARGB_8888**,我們可以修改成**Bitmap.Config.ARGB_4444** Bitmap.Config ARGB_4444:每個像素占四位,即A=4,R=4,G=4,B=4,那么一個像素點占4+4+4+4=16位 Bitmap.Config ARGB_8888:每個像素占八位,即A=8,R=8,G=8,B=8,那么一個像素點占8+8+8+8=32位 默認使用ARGB_8888,即一個像素占4個字節! ## 2)圖片壓縮 同樣是BitmapFactory.Options,我們通過**inSampleSize**設置縮放倍數,比如寫2,即長寬變為原來的1/2,圖片就是原來的1/4,如果不進行縮放的話設置為1即可!但是不能一味的壓縮,畢竟這個值太小 的話,圖片會很模糊,而且要避免圖片的拉伸變形,所以需要我們在程序中動態的計算,這個 inSampleSize的合適值,而Options中又有這樣一個方法:**inJustDecodeBounds**,將該參數設置為 true后,decodeFiel并不會分配內存空間,但是可以計算出原始圖片的長寬,調用 options.**outWidth**/**outHeight**獲取出圖片的寬高,然后通過一定的算法,即可得到適合的 inSampleSize,這里感謝**街神**提供的代碼——摘自鴻洋blog! ``` public static int caculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { int width = options.outWidth; int height = options.outHeight; int inSampleSize = 1; if (width > reqWidth || height > reqHeight) { int widthRadio = Math.round(width * 1.0f / reqWidth); int heightRadio = Math.round(height * 1.0f / reqHeight); inSampleSize = Math.max(widthRadio, heightRadio); } return inSampleSize; } ``` 然后使用下上述的方法即可: ``` BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; // 設置了此屬性一定要記得將值設置為false Bitmap bitmap = null; bitmap = BitmapFactory.decodeFile(url, options); options.inSampleSize = computeSampleSize(options,128,128); options.inPreferredConfig = Bitmap.Config.ARGB_4444; /* 下面兩個字段需要組合使用 */ options.inPurgeable = true; options.inInputShareable = true; options.inJustDecodeBounds = false; try { bitmap = BitmapFactory.decodeFile(url, options); } catch (OutOfMemoryError e) { Log.e(TAG, "OutOfMemoryError"); } ``` ## 3.及時回收圖像 如果引用了大量的Bitmap對象,而應用又不需要同時顯示所有圖片。可以將暫時不用到的Bitmap對象 及時回收掉。對于一些明確知道圖片使用情況的場景可以主動recycle回收,比如引導頁的圖片,使用 完就recycle,幀動畫,加載一張,畫一張,釋放一張!使用時加載,不顯示時直接置null或recycle! 比如:imageView.setImageResource(0); 不過某些情況下會出現特定圖片反復加載,釋放,再加載等,低效率的事情... ## 4.其他方法 下面這些方法,我并沒有用過,大家可以自行查閱相關資料: ### 1.簡單通過SoftReference引用方式管理圖片資源 建個SoftReference的hashmap 使用圖片時先查詢這個hashmap是否有softreference, softreference里的圖片是否為空, 如果為空就加載圖片到softreference并加入hashmap。 無需再代碼里顯式的處理圖片的回收與釋放,gc會自動處理資源的釋放。 這種方式處理起來簡單實用,能一定程度上避免前一種方法反復加載釋放的低效率。但還不夠優化。 **示例代碼:** ``` private Map<String, SoftReference<Bitmap>> imageMap = new HashMap<String, SoftReference<Bitmap>>(); public Bitmap loadBitmap(final String imageUrl,final ImageCallBack imageCallBack) { SoftReference<Bitmap> reference = imageMap.get(imageUrl); if(reference != null) { if(reference.get() != null) { return reference.get(); } } final Handler handler = new Handler() { public void handleMessage(final android.os.Message msg) { //加入到緩存中 Bitmap bitmap = (Bitmap)msg.obj; imageMap.put(imageUrl, new SoftReference<Bitmap>(bitmap)); if(imageCallBack != null) { imageCallBack.getBitmap(bitmap); } } }; new Thread(){ public void run() { Message message = handler.obtainMessage(); message.obj = downloadBitmap(imageUrl); handler.sendMessage(message); } }.start(); return null ; } // 從網上下載圖片 private Bitmap downloadBitmap (String imageUrl) { Bitmap bitmap = null; try { bitmap = BitmapFactory.decodeStream(new URL(imageUrl).openStream()); return bitmap ; } catch (Exception e) { e.printStackTrace(); return null; } } public interface ImageCallBack{ void getBitmap(Bitmap bitmap); } ``` ### 2.LruCache + sd的緩存方式 > Android 3.1版本起,官方還提供了LruCache來進行cache處理,當存儲Image的大小大于LruCache 設定的值,那么近期使用次數最少的圖片就會被回收掉,系統會自動釋放內存! **使用示例**: 步驟: 1)要先設置緩存圖片的內存大小,我這里設置為手機內存的1/8, 手機內存的獲取方式:int MAXMEMONRY = (int) (Runtime.getRuntime() .maxMemory() / 1024); 2)LruCache里面的鍵值對分別是URL和對應的圖片 3)重寫了一個叫做sizeOf的方法,返回的是圖片數量。 ``` private LruCache<String, Bitmap> mMemoryCache; private LruCacheUtils() { if (mMemoryCache == null) mMemoryCache = new LruCache<String, Bitmap>( MAXMEMONRY / 8) { @Override protected int sizeOf(String key, Bitmap bitmap) { // 重寫此方法來衡量每張圖片的大小,默認返回圖片數量。 return bitmap.getRowBytes() * bitmap.getHeight() / 1024; } @Override protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) { Log.v("tag", "hard cache is full , push to soft cache"); } }; } ``` 4)下面的方法分別是清空緩存、添加圖片到緩存、從緩存中取得圖片、從緩存中移除。 移除和清除緩存是必須要做的事,因為圖片緩存處理不當就會報內存溢出,所以一定要引起注意。 ``` public void clearCache() { if (mMemoryCache != null) { if (mMemoryCache.size() > 0) { Log.d("CacheUtils", "mMemoryCache.size() " + mMemoryCache.size()); mMemoryCache.evictAll(); Log.d("CacheUtils", "mMemoryCache.size()" + mMemoryCache.size()); } mMemoryCache = null; } } public synchronized void addBitmapToMemoryCache(String key, Bitmap bitmap) { if (mMemoryCache.get(key) == null) { if (key != null && bitmap != null) mMemoryCache.put(key, bitmap); } else Log.w(TAG, "the res is aready exits"); } public synchronized Bitmap getBitmapFromMemCache(String key) { Bitmap bm = mMemoryCache.get(key); if (key != null) { return bm; } return null; } /** * 移除緩存 * * @param key */ public synchronized void removeImageCache(String key) { if (key != null) { if (mMemoryCache != null) { Bitmap bm = mMemoryCache.remove(key); if (bm != null) bm.recycle(); } } } ``` 上述內容摘自——[圖片緩存之內存緩存技術LruCache,軟引用](http://blog.chinaunix.net/uid-26930580-id-4138306.html) ## 本節小結: > 本節給大家講解了OOM問題的發生緣由,也總結了一下網上給出的一些避免因Bitmap而引起OOM 的一些方案,因為公司做的APP都是地圖類的,很少涉及到圖片,所以筆者并沒有遇到過OOM的問題, 所以對此并不怎么熟悉~后續在進階課程的內存管理,我們再慢慢糾結這個OOM的問題,好的, 本節就到這里,謝謝~ **參考文獻**: [Android應用中OOM問題剖析和解決方案](http://www.runoob.com/w3cnote/android-oom.html)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看