精品伊人久久大香线蕉,开心久久婷婷综合中文字幕,杏田冲梨,人妻无码aⅴ不卡中文字幕

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
Android加載圖片致使內存溢出(Out of Memory異常)
userphoto

2022.05.08 湖南省

關注

時間  2019-11-06

標簽 android 加載 圖片 致使 內存 溢出 memory 異常 欄目 Android 繁體版

原文   https://my.oschina.net/u/593529/blog/139002

Android在加載大背景圖或者大量圖片時,常常致使內存溢出(Out of Memory Error),本文根據我處理這些問題的經歷及其它開發者的經驗,整理解決方案以下(部分代碼及文字出處沒法考證):

方案1、讀取圖片時注意方法的調用,適當壓縮

盡可能不要使用 setImageBitmap或 setImageResource或 BitmapFactory.decodeResource來設置一張大圖,由于這些函數在完成decode后,最終都是經過java層的 createBitmap來完成的,須要消耗更多內存。

所以,改用先經過 BitmapFactory.decodeStream方法,建立出一個bitmap,再將其設為ImageView的 source, decodeStream最大的秘密在于其直接調用JNI>>nativeDecodeAsset()來完成decode,無需再使用java層的createBitmap,從而節省了java層的空間。

        InputStream is = this.getResources().openRawResource(R.drawable.pic1); java

        BitmapFactory.Options options = new BitmapFactory.Options(); android

        options.inJustDecodeBounds = false; 算法

        options.inSampleSize = 10;   // widthhight設為原來的十分一 函數

        Bitmap btp = BitmapFactory.decodeStream(is, null, options); 性能

若是在讀取時加上圖片的Config參數,能夠跟有效減小加載的內存,從而跟有效阻止拋out of Memory異常。

  /** 優化

     * 以最省內存的方式讀取本地資源的圖片 this

     * @param context spa

     * @param resId .net

     * @return 線程

     */

    public static Bitmap readBitMap(Context context, int resId){ 

        BitmapFactory.Options opt = new BitmapFactory.Options();

        opt.inPreferredConfig = Bitmap.Config.RGB_565;

        opt.inPurgeable = true;

        opt.inInputShareable = true;

        // 獲取資源圖片

        InputStream is = context.getResources().openRawResource(resId);

        return BitmapFactory.decodeStream(is, null, opt);

        }

另外,decodeStream直接拿圖片來讀取字節碼, 不會根據機器的各類分辨率來自動適應,使用了decodeStream以后,須要在hdpi和mdpi,ldpi中配置相應的圖片資源, 不然在不一樣分辨率機器上都是一樣大小(像素點數量),顯示出來的大小就不對了。

方案2、在適當的時候及時回收圖片占用的內存

一般Activity或者Fragment在onStop/onDestroy時候就能夠釋放圖片資源:

 if(imageView != null && imageView.getDrawable() != null){     

      Bitmap oldBitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();    

      imageView.setImageDrawable(null);    

      if(oldBitmap != null){    

            oldBitmap.recycle();    

            oldBitmap = null;   

      }    

 }   

 // Other code.

 System.gc();

在釋放資源時,須要注意釋放的Bitmap或者相關的Drawable是否有被其它類引用。若是正常的調用,能夠經過 Bitmap.isRecycled()方法來判斷是否有被標記回收;而若是是被UI線程的界面相關代碼使用,就須要特別當心避免回收有可能被使用的資源,否則有可能拋出系統異常:

E/AndroidRuntime: java.lang.IllegalArgumentException: Cannot draw recycled bitmaps

而且該異常沒法有效捕捉并處理。

方案3、沒必要要的時候避免圖片的完整加載

只須要知道圖片大小的情形下,能夠不完整加載圖片到內存。

在使用 BitmapFactory壓縮圖片的時候, BitmapFactory.Options設置 inJustDecodeBounds為true后,再使用 decodeFile()等方法,能夠在不分配空間狀態下計算出圖片的大小。示例: 

 BitmapFactory.Options opts = new BitmapFactory.Options();    

 // 設置inJustDecodeBoundstrue    

 opts.inJustDecodeBounds = true   

 // 使用decodeFile方法獲得圖片的寬和高    

 BitmapFactory.decodeFile(path, opts);    

 // 打印出圖片的寬和高

 Log.d("example", opts.outWidth + "," + opts.outHeight);

(ps:原理其實就是經過圖片的頭部信息讀取圖片的基本信息)

方案4、優化Dalvik虛擬機的堆內存分配

堆(HEAP)是VM中占用內存最多的部分,一般是動態分配的。堆的大小不是一成不變的,一般有一個分配機制來控制它的大小。好比初始的HEAP是4M大,當4M的空間被占用超過75%的時候,從新分配堆為8M大;當8M被占用超過75%,分配堆為16M大。倒過來,當16M的堆利用不足30%的時候,縮減它的大小為8M大。從新設置堆的大小,尤為是壓縮,通常會涉及到內存的拷貝,因此變動堆的大小對效率有不良影響。

Heap Utilization是堆的利用率。當實際的利用率偏離這個百分比的時候,虛擬機會在GC的時候調整堆內存大小,讓實際占用率向個百分比靠攏。使用  dalvik.system.VMRuntime類提供的 setTargetHeapUtilization方法能夠加強程序堆內存的處理效率。

 private final static float TARGET_HEAP_UTILIZATION = 0.75f;    

 // 在程序onCreate時就能夠調用

 VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION);

方案5、自定義堆(Heap)內存大小

對于一些Android項目,影響性能瓶頸的主要是Android本身內存管理機制問題,目前手機廠商對RAM都比較吝嗇,對于軟件的流暢性來講RAM對性能的影響十分敏感,除了優化Dalvik虛擬機的堆內存分配外,咱們還能夠強制定義本身軟件的對內存大小,咱們使用Dalvik提供的  dalvik.system.VMRuntime類來設置最小堆內存為例:

 private final static int CWJ_HEAP_SIZE = 6 * 1024 * 1024 ;

 VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE); // 設置最小heap內存為6MB大小。

可是上面方法仍是存在問題,函數 setMinimumHeapSize 其實只是改變了堆的下限值,它能夠防止過于頻繁的堆內存分配,當設置最小堆內存大小超過上限值(Max Heap Size)時仍然采用堆的上限值,對于內存不足沒什么做用。

最后介紹一下圖片占用進程的內存算法。android中處理圖片的基礎類是Bitmap,顧名思義,就是位圖。占用內存的算法如:圖片的width*height*Config。

若是Config設置為ARGB_8888,那么上面的Config就是4。一張480*320的圖片占用的內存就是480*320*4 byte。

在默認狀況下android進程的內存占用量為16M,由于Bitmap他除了java中持有數據外,底層C++的 skia圖形庫還會持有一個SKBitmap對象,所以通常圖片占用內存推薦大小應該不超過8M。這個能夠調整,編譯源代碼時能夠設置參數。

本站僅提供存儲服務,所有內容均由用戶發布,如發現有害或侵權內容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
如何解決加載大圖片時內存溢出的問題
圖片處理OOM總結
Bitmap的生成流程之BitmapFactory.decodeResource VS BitmapFactory.decodeStream
Android內存溢出的解決辦法(僅供參考)
針對圖片性能優化的總結
Android Bitmap內存限制
更多類似文章 >>
生活服務
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯系客服!

聯系客服

主站蜘蛛池模板: 蓬溪县| 潼关县| 西平县| 甘孜县| 茌平县| 邵阳市| 黔西县| 徐汇区| 日喀则市| 盱眙县| 嵩明县| 桓台县| 桃源县| 黄大仙区| 佛山市| 金沙县| 分宜县| 恩平市| 怀远县| 长治县| 长沙市| 伊川县| 尚志市| 东城区| 信丰县| 海阳市| 淮滨县| 石楼县| 阿克苏市| 陕西省| 会同县| 芜湖市| 利川市| 东乌珠穆沁旗| 亳州市| 东乡族自治县| 宝山区| 邵阳市| 西充县| 中方县| 内江市|