bitmap設定画像サイズ縮小、メモリオーバーフロー/OutOfMemoryError回避の最適化方法


(回転)bitmap設定画像サイズ縮小、メモリオーバーフロー/OutOfMemoryError回避の最適化方法
AndroidのDalvik VMが1つのアプリケーションに約16 MBのメモリを供給していることはよく知られていますが、一般的に8 MBを超えた画像を処理するとOutOfMemoryError異常(メモリオーバーフロー異常)が表示され、以下のエラーが表示されます.
 20155392-byte external allocation too large for this process.
 VM won""t let us allocate 20155392 bytes
 Java.lang.OutOfMemoryError : bitmap size exceeds VM budget
    FileInputStream in;   
    in = new FileInputStream(path);   
    byte[] buffer = new byte[1024];   
    ByteArrayOutputStream out = new ByteArrayOutputStream();   
    int len = 0;   
    while ((len = in.read(buffer)) != -1) {   
        out.write(buffer, 0, len);   
    }   
    imageData = out.toByteArray();   
    Bitmap bitMap = BitmapFactory.decodeByteArray(imageData, 0,imageData.length);

以上、初めて閲覧画像を書き始めましたが、decodeByteArrayメソッドだけを見てSDカードから取得した画像のパスをbyte[]に変換してBitmapに割り当てました.もともとはパスから直接Bitmapを取得する方法があります.
Bitmap bitMap = BitmapFactory.decodeByteArray(path) ; 

しかし、表示しなければならない画像が大きすぎるため、プレビュー画像はメモリオーバーフローを提示します(しかし、材料を見つけて8 MBを越えた画像を処理するとOutOfMemoryError異常が現れ、最初の話をします)が、私が表示した画像は4 Mでも現れます
 20155392-byte external allocation too large for this process.
 VM won""t let us allocate 20155392 bytes
多分?20155392は19 Mの大きさの可能性があり、割り当てられた法度の16 Mの大きさを超えている可能性があります.メモリ不足の異常を防ぐために、BitmapFactoryを復号(プレビュー表示)します.Options?のプロパティを解決します.コードは次のとおりです.
1、パス経由で画像を取得する
    ImageView imageView=(ImageView)findViewById(R.id.image);  
    BitmapFactory.Options options = new BitmapFactory.Options();  
    options.inSampleSize=2;//              ,                  
    options.inTempStorage = new byte[5*1024]; //  16MB       (         ,   )  
    Bitmap bitMap = BitmapFactory.decodeFile(    , options);   
    imageView.setImageBitmap(bitMap);  

2、Uri経由で画像を取る
    Bitmap bitmap = BitmapFactory.decodeStream(cr.openInputStream(uri), null, options);   

以上のコードはメモリオーバーフローを最適化できますが、画像のサイズを変更するだけで、メモリオーバーフローを完全に解決することはできません.
以下はネットで見つけた資料です.
★Androidにはいくつかの機能を最適化する方法があります.
●? 最初のメモリについては、Androidスタックメモリを参考にしても、Dalvik仮想マシンのスタックメモリ割り当てを自分で定義し、最適化することができます●?根本的なタイプでは、Javaには実際のポインタがないため、敏感な演算ではNDKを借りて完成しなければならない.興味深いことに、GoogleがNDKを発売したのは、OpenGL ESのサポートなど、ゲーム開発者を助けるためかもしれません.ローカルコードがグラフィックインタフェースを操作する必要があります.●? グラフィックオブジェクトの最適化は、Android上のBitmapオブジェクトが焼失した場合、recycle()メソッドを使用してGCにBitmapオブジェクトを受信して引き継ぐことを表示することができます.
    if(bitmapObject.isRecycled()==false) //                 
             bitmapObject.recycle();   

今のところ体系はアニメーションに対して力の弱い知恵を支えて従来の応用の补间の移行の结果に対してできて、しかしゲームにとって普通の美工はGIFの体式のフォーマットの同一の処理の惩罚に惯れたかもしれなくて、今Androidの体系はGIFの第1フレームだけをプレビューすることができて、J 2 MEの中で过程のスレッドと自分で解析器の体式のフォーマットを书いてGIF 89の构造の资料を読むことができます.●多くの半Android携帯電話には物理的なボタンがあまりないので、ジェスチャーでGestureDetectorと重力誘導を認識して操作を実現することを想像する必要があります.私たちは問題を誤って操作したノイズ低減処理の罰を推敲しなければならない.
Androidスタックのメモリも自分でサイズを定義できますか?一部の大型Androidプロジェクトやゲームにとってアルゴリズム処理の罰には問題がないほか、機能のボトルネックに影響を与える主はAndroid自体のメモリ管理メカニズムの問題であれば、携帯電話メーカーはRAMに対してけちで、ソフトウェアの流暢性にとってRAMが機能に与える影響は10分敏感で、前回Androidがネットを開いたことで述べたDalvik仮想マシンのスタックメモリの最適化に加えて、また、Dalvikが供給するdalvikを適用して、自分のソフトウェアのメモリサイズを強制的に定義することもできます.system.VMRuntimeクラスで最小ヒープメモリを設定する例:
    private final static int CWJ_HEAP_SIZE = 6* 1024* 1024 ;         
    VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE); //    heap   6MB  。      
    private final static int CWJ_HEAP_SIZE = 6* 1024* 1024 ; VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE); //    heap   6MB  。  

もちろんメモリの不足に対しては,プロセス手動干渉を介してGCの行方を処理することもでき,我々は次に具体的な応用について述べる.Dalvik仮想マシンのスタックメモリ割り当てを最適化Androidプラットフォームにとって、その管理層アプリケーションのDalvik JavaVMは、現在の発揮解析から見ると、処理罰を最適化することができるところがたくさんあります.例えば、大規模なゲームや資料を消費するアプリケーションを開発する中で、手動干渉幹とGC処理罰、dalvikを推敲することができます.system.VMRuntimeクラスが供給するsetTargetHeapUtilizationメソッドは、法度スタックメモリの処理ペナルティの効力を強化することができる.もちろん具体的にはオープンソースエンジニアリングを参考にすることができますが、ここでは応用方法を説明します:private final static floatTARGET_HEAP_UTILIZATION = 0.75f;        private final static floatTARGET_HEAP_UTILIZATION = 0.75f;
法度onCreateで呼び出すことができます
VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION);        
VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION);

AndroidシステムでビットマップBitmapを読み取る場合.仮想マシンの画像に割り当てられるスタックのサイズは8 Mしかありません.だから、どのように画像を呼び出しても、あまりにも大きな仮想マシンは必ずそのエラーを報告します.画像メモリの予算を超えたエラーです.java.lang.OutOfMemoryError:bitmap size exceeds VM budgetこの問題に遭遇したのは、引き継ぎ資料を受け取っていないからだ.
?
public void distoryBitmap(){       
    if(null!=bmb&&!bmb.isRecycled())       
        bmb.recycle();     
}

?上のコードを呼び出すと、この問題を根本的に解決することができます.ただし、viewのonDraw()で呼び出さないでください.onDraw()メソッドはシステムのループ呼び出しです.画像が開く限り、システムは絶えずこの方法を呼び出す.最良の解決計画は、カスタムViewにinit()初期化方法のヘッダ呼び出しを追加することである.または、機関関数の上部で呼び出されます.