2010-06-13 9 views
19

Sto riscontrando un problema con bitmap su un'applicazione Android su cui sto lavorando. Ciò che si suppone accada è che l'applicazione scarica le immagini da un sito Web, le salva sul dispositivo, le carica in memoria come bitmap in un arraylist e le visualizza all'utente. Funziona tutto bene quando l'applicazione viene avviata per la prima volta. Tuttavia, ho aggiunto un'opzione di aggiornamento per l'utente in cui sono state eliminate le immagini e il processo descritto sopra inizia dappertutto.Errore "Trying to use bitmap recycled" per Android?

Il mio problema: utilizzando l'opzione di aggiornamento le vecchie immagini erano ancora in memoria e avrei rapidamente ottenuto OutOfMemoryErrors. Quindi, se le immagini vengono aggiornate, l'ho fatto scorrere attraverso l'arrayylist e riciclare le vecchie immagini. Tuttavia, quando l'applicazione va a caricare le nuove immagini nell'array, si blocca con un errore "Tentativo di utilizzare la bitmap riciclata".

Per quanto ne so, riciclare una bitmap distrugge la bitmap e libera la sua memoria per altri oggetti. Se voglio usare di nuovo la bitmap, deve essere reinizializzata. Credo che lo sto facendo quando i nuovi file vengono caricati nell'arrayylist, ma qualcosa è ancora sbagliato. Qualsiasi aiuto è molto apprezzato in quanto è molto frustrante. Il codice problema è sotto. Grazie!

public void fillUI(final int refresh) { 
// Recycle the images to avoid memory leaks 
if(refresh==1) { 
    for(int x=0; x<images.size(); x++) 
     images.get(x).recycle(); 
    images.clear(); 
    selImage=-1; // Reset the selected image variable 
} 
final ProgressDialog progressDialog = ProgressDialog.show(this, null, this.getString(R.string.loadingImages)); 
// Create the array with the image bitmaps in it 
new Thread(new Runnable() { 
    public void run() { 
     Looper.prepare(); 
     File[] fileList = new File("/data/data/[package name]/files/").listFiles(); 
     if(fileList!=null) { 
      for(int x=0; x<fileList.length; x++) { 
       try { 
        images.add(BitmapFactory.decodeFile("/data/data/[package name]/files/" + fileList[x].getName())); 
       } catch (OutOfMemoryError ome) { 
        Log.i(LOG_FILE, "out of memory again :("); 
       } 
      } 
      Collections.reverse(images); 
     } 
     fillUiHandler.sendEmptyMessage(0); 
    } 
}).start(); 

fillUiHandler = new Handler() { 
    public void handleMessage(Message msg) { 
     progressDialog.dismiss(); 
    } 
}; 

}

risposta

19

in realtà non hanno bisogno di chiamare il metodo di riciclo qui. Il pulsante di aggiornamento dovrebbe semplicemente cancellare l'array, il garbage collector libererà la memoria in un secondo momento. Se ottieni OutOfMemory significa che alcuni altri oggetti fanno ancora riferimento alle tue vecchie immagini e Garbage Collector non può rimuoverli.

È possibile che alcune immagini visualizzino le immagini bitmap e mantengano riferimenti a tali bitmap. Non è possibile rimuovere i vecchi bitmap mentre sono ancora visualizzati. Quindi una possibile soluzione è cancellare anche ImageVIews. Dopodiché puoi cancellare l'array e riempirlo con nuove immagini.

Ricicla libera la memoria ma alcuni ImageView continua a visualizzare la bitmap e non può farlo dopo il riciclo, ecco perché ottieni "Provare a usare bitmap riciclato".

Queste sono tutte solo supposizioni perché non riesco a vedere il codice completo.

+3

reg. "In realtà non è necessario chiamare il metodo di riciclo qui". Hm, interessante. Finora quello che ho letto sul web, ho anche pensato che fosse il modo di farlo e dovrebbe essere chiamato. L'ho sempre definito anche io. Ho anche riscontrato problemi di memoria quando utilizzo molte bitmap. Un buon modo per ridurre i problemi di memoria è usare le cache SoftReference, come suggerito da Romain Guy. Lo usa ad esempio in http://shelves.googlecode.com/svn/trunk/Shelves/src/org/curiouscreature/android/shelves/util/ImageUtilities.java Informazioni su SoftReferences: http: //java.sun. it/j2se/1.5.0/docs/api/java/lang/ref/SoftReference.html –

+4

Il riciclo è buono ma non è richiesto. GC pulirà comunque la memoria. Riciclare lo pulirà più velocemente. Questo è il modo in cui lo capisco. – Fedor

+1

Grazie Fedor! Mi sono assicurato di annullare tutte le viste che utilizzavano le bitmap prima di cancellare e ricreare l'array e questo ha fatto il trucco. :) – Mike

4

Se la memoria è molto grande, è meglio riciclare la bitmap da soli. GC non può essere controllato.

Problemi correlati