Wie Speicher korrekt freigeben?

  • Hallo Leute,


    ich hänge schon länger an einem Problem, das mir mittlerweile Kopfschmerzen bereitet.
    In meiner App ist es in einer Activity möglich ein Bild entweder aus der Gallerie auszuwählen oder per Kamera ein neues aufzunehmen. Das Foto wird auf Bildschirmgröße skaliert und in einem festen Ordner gespeichert. Zusätzlich wird es noch in einem kleinen Vorschau-ImageView angezeigt. Der Nutzer kann noch diverse Einstellungen tätigen und dann per Klick auf "fertig" zur nächsten Activity wechseln, in der das Bild geladen wird und als Hintergrundbild der gesamten Activity angezeigt wird. Daneben gibt es noch eine weitere Activity, die das gewählt Bild ebenfalls als Hintergrund anzeigt.


    Am Anfang hatte ich noch alle paar klicks einen OutOfMemory Error, da Bilder jeder Größe geladen wurden und nicht skaliert wurden, das habe ich mittlerweile behoben.


    Trotzdem bekomme ich, nachdem ich in allen Activities unterwegs war und in der ersten wieder ein neues Hintergrundbild wählen möchte, immer wieder einen OutOfMemoryError.


    Jetzt meine Frage: Kann es sein, dass die Activities die Bilder jeweils in den Speicher laden aber beim Verlassen nicht mehr freigeben? Das wäre meine einzige Erklärung, da es beim ersten Versuch immer klappt. Erst wenn ich die App eine Weile nutze, kommt der Fehler.


    Mein Ansatz war, das Bitmap nach dem Zuweisen zum imageView auf null zu setzen, um dem Garbage Collector zu signalisieren, dass er aufräumen darf, das scheint aber nichts zu bringen.


    Ich habe die Exceptions abgefangen, damit die App nicht abstürzt. Wenn ich jetzt minimiere und den Cache der Anwendung leere, geht alles wieder.
    Gibt es eine Möglichkeit den Cache der App während der Laufzeit zu leeren?


    Ich hoffe, das Problem ausreichend erklärt zu haben ;)
    Vielleicht kann ja jemand helfen, würde mich sehr freuen!

  • Hi starsky128,


    Zitat

    Mein Ansatz war, das Bitmap nach dem Zuweisen zum imageView auf null zu setzen, um dem Garbage Collector zu signalisieren, dass er aufräumen darf, das scheint aber nichts zu bringen.


    Mittels der Methode "recycle()" des Bitmap Objektes kannst du dem Garbage Collector dis signalisieren.

    Achtung das ist nur eine Vermutung ich kann mich dabei auch irren:
    Wenn du diesen Weg gehen möchtest, musst du schauen ob bei der Zuweisung des Bildes an die ImageView eine "tiefe Kopie" des Bildes gemacht wird. Falls nicht, kann es sein das wenn du das Bild "frei gibst", deine ImageView dann nix mehr anzeigt weil das Bild auf das sie verweist gelöscht wurde.


    Mfg Titus

  • du solltest es gar nicht nötig haben, irgendwelche expliziten funktionen zum freigeben aufrufen zu müssen.


    Guck aber mal ob du nicht irgendwas an Speicher NoGos gemacht hast, wie zum beispiel einen Context als final zu deklarieren oder irgendwie in einer statischen weise zu blockieren, bspw. wenn dein Bitmap static wäre, dann wäre das der fall.

  • titus: Deine Vermutung bewahrheitet sich leider ;)


    Stefan: nichts dergleichen..



    Ich habe gerade festgestellt, dass ich nichtmal in den anderen Activities gewesen sein muss, damit der Fehler auftritt.
    Es reicht wenn ich ein Bild wähle, danach ein neues Bild wähle und dann wieder.. spätestens beim drittel mal gibts einen OutOfMemoryError.
    Dabei wird das Bild jedes mal in die gleiche Bitmap geladen, also überschrieben.



    Ich zeig mal hier einpaar Code Beispiele, vielleicht ist meine Vorgehensweise auch einfach schlecht?


    Der User kann über verschiedene Buttons entweder über Galerie oder Kamera ein Bild wählen.
    In der onActivityResult für die Kamera siehts so aus:

    Java
    b = generateBitmap(IMG_TEMP_PATH,SCREEN_HEIGHT,SCREEN_WIDTH); 
    
    
    // b=Bitmap
    // generateBitmap nimmt das von der Kamera geschossene Bild (liegt im Standardpfad IMG_TEMP_PATH) und skaliert es auf Bildschirmgröße
    
    
     new SaveImageTask().execute(); // dazu gleich mehr


    Für die Gallerie sieht es so aus:








    Ich hoffe man kann folgen ;)

  • also ich sehe nichts relevantes.
    allerdings sehe ich nicht wo das b in doInBackground herkommt.
    Globale variable?


    und du musst nicht jede variable immer null setzen wenn du sie nicht mehr brauchst, das gibt den speicher meines wissens nach auch nicht schneller frei, da z.B. in der if anwendung das bitmap sowieso nach der if nicht mehr verfügbar wäre (bleibt natürlich im speicher da es ja im imageview ist), aber das File z.B. nicht.
    das ist meines erachtens etwas unschön das immer null zusetzen

  • Hab ich mir angeschaut und auch versucht umzusetzen, hat alles nicht geholfen :-/ Irgendwo stimmt was nicht, wenn ich bloß wüsste was..



    edit:

    Externer Inhalt www.youtube.com
    Inhalte von externen Seiten werden ohne Ihre Zustimmung nicht automatisch geladen und angezeigt.
    Durch die Aktivierung der externen Inhalte erklären Sie sich damit einverstanden, dass personenbezogene Daten an Drittplattformen übermittelt werden. Mehr Informationen dazu haben wir in unserer Datenschutzerklärung zur Verfügung gestellt.
    dieses video ist sehr hilfreich!


    habe im manifest die Option android:largeHeap="true" hinzugefügt, seither keine Abstürze mehr :) Das löst das eigentliche Problem zwar noch nicht, jedoch zumindest mal die Symptome und es macht meine App nutzbar ohne dauer Abstürze ertragen zu müssen. Werde mir jetzt mal den Rest anschauen, in der Hoffnung das Problem beim Kragen zu packen ;)

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!