160 Stimmen

java.lang.OutOfMemoryError: Bitmap-Größe überschreitet VM-Budget - Android

Ich habe eine Anwendung entwickelt, die viele Bilder auf Android verwendet.

Die App läuft einmal, füllt die Informationen auf dem Bildschirm ( Layouts , Listviews , Textviews , ImageViews usw.) und der Benutzer liest die Informationen.

Es gibt keine Animationen, keine Spezialeffekte oder andere Dinge, die den Speicher füllen können. Manchmal können sich die Zeichenobjekte ändern. Einige sind Android-Ressourcen und einige sind Dateien, die in einem Ordner auf der SDCARD gespeichert sind.

Dann verlässt der Benutzer (die onDestroy Methode ausgeführt wird und die App im Speicher der VM verbleibt) und dann irgendwann der Benutzer wieder eintritt.

Jedes Mal, wenn der Benutzer die Anwendung aufruft, kann ich sehen, wie der Speicher immer mehr wächst, bis der Benutzer die java.lang.OutOfMemoryError .

Was ist also der beste/richtige Weg, um mit vielen Bildern umzugehen?

Sollte ich sie in statische Methoden setzen, so dass sie nicht die ganze Zeit geladen werden? Muss ich das Layout oder die Bilder, die im Layout verwendet werden, auf eine besondere Weise reinigen?

0voto

Guy Smith Punkte 178

FWIW, hier ist ein leichtgewichtiger Bitmap-Cache, den ich programmiert habe und seit ein paar Monaten verwende. Es ist nicht all-the-bells-and-whistles, so lesen Sie den Code, bevor Sie es verwenden.

/**
 * Lightweight cache for Bitmap objects. 
 * 
 * There is no thread-safety built into this class. 
 * 
 * Note: you may wish to create bitmaps using the application-context, rather than the activity-context. 
 * I believe the activity-context has a reference to the Activity object. 
 * So for as long as the bitmap exists, it will have an indirect link to the activity, 
 * and prevent the garbaage collector from disposing the activity object, leading to memory leaks. 
 */
public class BitmapCache { 

    private Hashtable<String,ArrayList<Bitmap>> hashtable = new Hashtable<String, ArrayList<Bitmap>>();  

    private StringBuilder sb = new StringBuilder(); 

    public BitmapCache() { 
    } 

    /**
     * A Bitmap with the given width and height will be returned. 
     * It is removed from the cache. 
     * 
     * An attempt is made to return the correct config, but for unusual configs (as at 30may13) this might not happen.  
     * 
     * Note that thread-safety is the caller's responsibility. 
     */
    public Bitmap get(int width, int height, Bitmap.Config config) { 
        String key = getKey(width, height, config); 
        ArrayList<Bitmap> list = getList(key); 
        int listSize = list.size();
        if (listSize>0) { 
            return list.remove(listSize-1); 
        } else { 
            try { 
                return Bitmap.createBitmap(width, height, config);
            } catch (RuntimeException e) { 
                // TODO: Test appendHockeyApp() works. 
                App.appendHockeyApp("BitmapCache has "+hashtable.size()+":"+listSize+" request "+width+"x"+height); 
                throw e ; 
            }
        }
    }

    /**
     * Puts a Bitmap object into the cache. 
     * 
     * Note that thread-safety is the caller's responsibility. 
     */
    public void put(Bitmap bitmap) { 
        if (bitmap==null) return ; 
        String key = getKey(bitmap); 
        ArrayList<Bitmap> list = getList(key); 
        list.add(bitmap); 
    }

    private ArrayList<Bitmap> getList(String key) {
        ArrayList<Bitmap> list = hashtable.get(key);
        if (list==null) { 
            list = new ArrayList<Bitmap>(); 
            hashtable.put(key, list); 
        }
        return list;
    } 

    private String getKey(Bitmap bitmap) {
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        Config config = bitmap.getConfig();
        return getKey(width, height, config);
    }

    private String getKey(int width, int height, Config config) {
        sb.setLength(0); 
        sb.append(width); 
        sb.append("x"); 
        sb.append(height); 
        sb.append(" "); 
        switch (config) {
        case ALPHA_8:
            sb.append("ALPHA_8"); 
            break;
        case ARGB_4444:
            sb.append("ARGB_4444"); 
            break;
        case ARGB_8888:
            sb.append("ARGB_8888"); 
            break;
        case RGB_565:
            sb.append("RGB_565"); 
            break;
        default:
            sb.append("unknown"); 
            break; 
        }
        return sb.toString();
    }

}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X