0

私のアプリケーションには、データベースからデコードされる 350 を超える画像があります。画像データからビットマップを作成し、デバイスの画面解像度に基づいてスケーリングします。これらのビットマップをすべてメモリに保持しようとすると、outOfMemory 例外が発生しました。次に、OutOfMemoryExceptions を回避する方法として、BitmapFactory.Options.inPurgeable がさまざまな場所で推奨されています。

BitmapFactory.Options options = new BitmapFactory.Options();
options.inPurgeable = true;
options.inInputShareable = true;

Bitmap bitmap = BitmapFactory.decodeByteArray(imagaeData, 0, size, options);
...
..
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, reqWidth, reqHeight, true); 

このスケーリングされたビットマップを HashMap にキャッシュし、画像ビューに使用しています。ここでも、ビットマップをメモリにロードしているときに OutOfMemory 例外に直面しています。私の場合、inPurgeableが機能しているかどうかはわかりません。スケーリングされたビットマップがバイト配列を参照するかどうか疑問に思っています。スケーリングされたビットマップを使用しているため、decodeByteArray で使用される inPurgeable オプションの効果がありますか。このビットマップ メモリの問題を処理する方法がわかりません。あなたの助けに感謝。

4

4 に答える 4

0

BitmapFactory.Options.inScaled と BitmapFactory.Options を試すことができます。inScreenDensity を使用して、スケーリングされたビットマップを取得します。

また、ビットマップをメモリにキャッシュするためのより良い方法が必要です。ビットマップの HashMap で Bitmap の WeakReference を保持することをお勧めします。単純な LRU キャッシュの実装のために LinkedHashMap に切り替えることができます。

すべての画像をキャッシュする必要はありません。画像が 1 つの画面に表示される機会は決してないからです。

于 2013-05-27T09:09:18.160 に答える
0

この方法を使用して、最初に画像サイズを縮小します (ファイルは SD カード上の写真を指します)。

//decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f){
    try {
        //decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;
        FileInputStream stream1=new FileInputStream(f);
        BitmapFactory.decodeStream(stream1,null,o);
        stream1.close();

        //Find the correct scale value. It should be the power of 2.
        // maximum size is 50
        final int REQUIRED_SIZE=40;
        int width_tmp=o.outWidth, height_tmp=o.outHeight;
        int scale=1;
        while(true){
            if(width_tmp/2<=REQUIRED_SIZE || height_tmp/2<=REQUIRED_SIZE)
                break;
            width_tmp/=2;
            height_tmp/=2;
            scale*=2;
        }

        //decode with inSampleSize
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize=scale;
        FileInputStream stream2=new FileInputStream(f);
        Bitmap bitmap=BitmapFactory.decodeStream(stream2, null, o2);
        stream2.close();
        return bitmap;
    } catch (FileNotFoundException e) {
    } 
    catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

// 上記のメソッドを呼び出す方法は次のとおりです

                    String path = "/mnt/sdcard/DCIM/camera/IMG_2001.jpg";
                    Drawable background = hash_map.get(path);
                    if (background == null) {
                    try {
                        Bitmap bitmap = decodeFile(new File(path));
                        background = new BitmapDrawable(bitmap);
                        if (hash_map.size() > 600) {
                            // to prevent HashMap from growing too large.
                            hash_map.clear();
                        }
                        hash_map.put(path, background);
                    } catch (Throwable e) {
                        // in case there is an exception, like running out of memory.
                        if (e instanceof OutOfMemoryError) {
                            hash_map.clear();
                        }
                    }
                 }
于 2014-04-21T21:03:35.553 に答える
0

350枚の画像はかなり多いです。一度にすべてが必要ですか?

また、スケーリングされたビットマップを作成すると、それらがメモリに2回保存されます->メモリ内の700枚の画像は多すぎます。inScaleオプションで使用して、再度 350 に減らし、さらにメモリ フットプリントを減らした方がよいかどうかを確認する必要があります。

最適化された方法でも、350 枚の画像は多すぎると思います。遅延読み込みソリューションを検討する必要があります。

于 2013-05-27T09:02:32.427 に答える