Autore Topic: Applicazione non risponde e outofmemory  (Letto 1173 volte)

Offline elfo83

  • Utente normale
  • ***
  • Post: 283
  • Respect: +23
    • Mostra profilo
  • Sistema operativo:
    Mac OS 10.8.2
Applicazione non risponde e outofmemory
« il: 05 Luglio 2013, 21:23:52 CEST »
0
Ciao ragazzi, ho in un'attività una lista che ha 4 layout diversi come children. Quando scorro la lista e arrivo ad uno specifico figlio che ha un certo layout, l'applicazione si blocca per un po' ed esce il messaggio application not responding. Quel tipo di layout ha un'immagine di sfondo che carico con un ImageLoader e presumo che dipenda da questo. Inoltre, spesso l'applicazione va outofmemory ed il motivo è sempre lo stesso. Qualcuno può dare un'occhiata a questo codice e vedere se c'è qualcosa che non va?

Questo è l'errore:
Codice: [Seleziona]
07-05 15:05:06.535: W/dalvikvm(30675): threadid=1: thread exiting with uncaught exception (group=0x40ab7210)
07-05 15:05:06.543: E/AndroidRuntime(30675): FATAL EXCEPTION: main
07-05 15:05:06.543: E/AndroidRuntime(30675): java.lang.OutOfMemoryError
07-05 15:05:06.543: E/AndroidRuntime(30675):         at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
07-05 15:05:06.543: E/AndroidRuntime(30675):         at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:530)
07-05 15:05:06.543: E/AndroidRuntime(30675):         at com.qriket.qriket.utils.ImgLoader.decodeFile(ImgLoader.java:282)
07-05 15:05:06.543: E/AndroidRuntime(30675):         at com.qriket.qriket.utils.ImgLoader.DisplayImage(ImgLoader.java:76)
07-05 15:05:06.543: E/AndroidRuntime(30675):         at com.qriket.qriket.utils.ImgLoader.DisplayImage(ImgLoader.java:62)
07-05 15:05:06.543: E/AndroidRuntime(30675):         at com.qriket.qriket.profile.profile$ListProfileAdp.getView(profile.java:1336)
07-05 15:05:06.543: E/AndroidRuntime(30675):         at com.qriket.qriket.profile.profile.displayListActivity(profile.java:1096)
07-05 15:05:06.543: E/AndroidRuntime(30675):         at com.qriket.qriket.profile.profile.access$10(profile.java:1009)
07-05 15:05:06.543: E/AndroidRuntime(30675):         at com.qriket.qriket.profile.profile$moreDonorsResponse.onResponseReceived(profile.java:924)
07-05 15:05:06.543: E/AndroidRuntime(30675):         at com.qriket.qriket.httpclient.HttpAsyncTask.onPostExecute(HttpAsyncTask.java:166)
07-05 15:05:06.543: E/AndroidRuntime(30675):         at com.qriket.qriket.httpclient.HttpAsyncTask.onPostExecute(HttpAsyncTask.java:1)
07-05 15:05:06.543: E/AndroidRuntime(30675):         at android.os.AsyncTask.finish(AsyncTask.java:602)
07-05 15:05:06.543: E/AndroidRuntime(30675):         at android.os.AsyncTask.access$600(AsyncTask.java:156)
07-05 15:05:06.543: E/AndroidRuntime(30675):         at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:615)
07-05 15:05:06.543: E/AndroidRuntime(30675):         at android.os.Handler.dispatchMessage(Handler.java:99)
07-05 15:05:06.543: E/AndroidRuntime(30675):         at android.os.Looper.loop(Looper.java:137)
07-05 15:05:06.543: E/AndroidRuntime(30675):         at android.app.ActivityThread.main(ActivityThread.java:4697)
07-05 15:05:06.543: E/AndroidRuntime(30675):         at java.lang.reflect.Method.invokeNative(Native Method)
07-05 15:05:06.543: E/AndroidRuntime(30675):         at java.lang.reflect.Method.invoke(Method.java:511)
07-05 15:05:06.543: E/AndroidRuntime(30675):         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:787)
07-05 15:05:06.543: E/AndroidRuntime(30675):         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:554)
07-05 15:05:06.543: E/AndroidRuntime(30675):         at dalvik.system.NativeStart.main(Native Method)

Queste sono le classi che uso per il caricamento delle immagini...fonte che ho modificato http://www.technotalkative.com/android-load-images-from-web-and-caching/

ImgLoader class:
Codice (Java): [Seleziona]
public class ImgLoader
{
        private final int maxRoundWidth=150;
    MemoryCache memoryCache=new MemoryCache();
    FileCache fileCache;
    private Map<ImageView, String> imageViews=Collections.synchronizedMap(new WeakHashMap<ImageView, String>());
    private CallbackWrapper wrapper;
    private Handler handler;
    public ImgLoader(Context context){
        photoLoaderThread.setPriority(Thread.NORM_PRIORITY-1);
        fileCache=new FileCache(context);
        wrapper=null;
        handler=null;
    }
   
    public ImgLoader(Context context,CallbackWrapper wrapper,Handler handler){
        photoLoaderThread.setPriority(Thread.NORM_PRIORITY-1);
        this.wrapper=wrapper;
        this.handler=handler;
        fileCache=new FileCache(context);
    }

    public void DisplayImage(String url, Activity activity, ImageView imageView)
    {
        DisplayImage(url,activity,imageView,false);
    }
   
    public void DisplayImage(String url, Activity activity, ImageView imageView,boolean skipRound)
    {
        imageViews.put(imageView, url);
        Bitmap bitmap=memoryCache.get(url);
        if(bitmap!=null)
        {
                displayImage(bitmap,imageView,skipRound);
        }
        else
        {
           
                bitmap = decodeFile(fileCache.getFile(url));
                if(bitmap!=null)
                        displayImage(bitmap,imageView,skipRound);
           
         
               
               
        }  
        queuePhoto(url, activity, imageView,skipRound);
    }
       
    private void queuePhoto(String url, Activity activity, ImageView imageView,boolean skipRound)
    {
        photosQueue.Clean(imageView);
        PhotoToLoad p=new PhotoToLoad(url, imageView,skipRound);
        synchronized(photosQueue.photosToLoad){
            photosQueue.photosToLoad.push(p);
            photosQueue.photosToLoad.notifyAll();
        }
       
        if(photoLoaderThread.getState()==Thread.State.NEW)
            photoLoaderThread.start();
    }
   
    private class PhotoToLoad
    {
        public String url;
        public ImageView imageView;
        public boolean skipRound;
        public PhotoToLoad(String u, ImageView i,boolean s){
            url=u;
            imageView=i;
            skipRound=s;
        }
    }
   
    public void stopThread()
    {
        photoLoaderThread.interrupt();
    }
   
    PhotosQueue photosQueue=new PhotosQueue();
    class PhotosQueue
    {
        private Stack<PhotoToLoad> photosToLoad=new Stack<PhotoToLoad>();
        public void Clean(ImageView image)
        {
            for(int j=0 ;j<photosToLoad.size();){
                if(photosToLoad.get(j).imageView==image)
                    photosToLoad.remove(j);
                else
                    ++j;
            }
        }
    }
   
    PhotosLoader photoLoaderThread=new PhotosLoader();
    class PhotosLoader extends Thread {
        public void run() {
            try {
                while(true)
                {
                    if(photosQueue.photosToLoad.size()==0)
                        synchronized(photosQueue.photosToLoad){
                            photosQueue.photosToLoad.wait();
                        }
                    if(photosQueue.photosToLoad.size()!=0)
                    {
                        PhotoToLoad photoToLoad;
                        synchronized(photosQueue.photosToLoad){
                            photoToLoad=photosQueue.photosToLoad.pop();
                        }
                        Bitmap bmp=getBitmap(photoToLoad.url);
                        memoryCache.put(photoToLoad.url, bmp);
                        String tag=imageViews.get(photoToLoad.imageView);
                        if(tag!=null && tag.equals(photoToLoad.url)){
                            BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad.imageView,photoToLoad.skipRound);
                            Activity a=(Activity)photoToLoad.imageView.getContext();
                            a.runOnUiThread(bd);
                        }
                    }
                    if(Thread.interrupted())
                        break;
                }
            } catch (InterruptedException e) {

            }
        }
    }
   
    public File getCacheFile(String url)
    {
       
        if(url=="")
                return null;
       
        return fileCache.getFile(url);
    }
   
    public void setBgBitmap(String url,View view)
    {
        if(url!=null && url!="")
        {
                if(view!=null)
                {
                        Bitmap bitmap = getBitmap(url);
                        BitmapDrawable bd = new BitmapDrawable(bitmap);
                        view.setBackgroundDrawable(bd);
               
                }
        }
    }
    private Bitmap getBitmap(String url)
    {
        File f=fileCache.getFile(url);
        for (int i = 0; i < 3; i++)
        {
                try {
                    Bitmap bitmap=null;
                    URL imageUrl = new URL(url);
                    HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();
                    conn.setConnectTimeout(30000);
                    conn.setReadTimeout(30000);
                    try
                    {
                            InputStream is=conn.getInputStream();
                            OutputStream os = new FileOutputStream(f);
                            utils.CopyStream(is, os);
                            os.close();
                            bitmap = decodeFile(f);
                            if(handler!=null)
                            {
                                handler.post(wrapper);
                            } else
                            {

                            }
                    }
                    catch (Exception ex){
                           ex.printStackTrace();
                        }
                        finally
                        {
                                conn.disconnect();
                        }
                    return bitmap;
                } catch (Exception ex){
                   ex.printStackTrace();
                }
        }
        return null;
    }
 
    private Bitmap decodeFile(File f){
        try {
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inPurgeable = true;
            o.inInputShareable=true;
            o.inJustDecodeBounds = true;
         
            BitmapFactory.decodeStream(new FileInputStream(f),null,o);
           
            final int REQUIRED_SIZE=640;
            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;
            }
           
            BitmapFactory.Options o2 = new BitmapFactory.Options();
            o2.inSampleSize=scale;
            o.inJustDecodeBounds = false;
            return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
        } catch (FileNotFoundException e) {}
        return null;
    }

   
   
    class BitmapDisplayer implements Runnable
    {
        Bitmap bitmap;
        ImageView imageView;
        boolean skipRound;
        public BitmapDisplayer(Bitmap b, ImageView i, boolean s)
        {
                bitmap=b;
                imageView=i;
                skipRound=s;
        }
       
        public void run()
        {
            if(bitmap!=null && imageView!=null)
            {
                imageView.setScaleType(ScaleType.CENTER_CROP);
                if(imageView.getWidth()<maxRoundWidth && imageView.getHeight()<maxRoundWidth && imageView.getWidth()>1 && imageView.getHeight()>1 && !skipRound)
                        imageView.setImageBitmap(getRoundedCornerBitmap(bitmap,imageView.getWidth(),imageView.getHeight()));
                else
                        imageView.setImageBitmap(bitmap);
            }
        }
    }
   
   
   
    private void displayImage(Bitmap bitmap, ImageView imageView, boolean skipRound)
    {
        if(bitmap!=null && imageView!=null)
        {
                imageView.setScaleType(ScaleType.CENTER_INSIDE);
                if(imageView.getWidth()<maxRoundWidth && imageView.getHeight()<maxRoundWidth && imageView.getWidth()>1 && imageView.getHeight()>1 && !skipRound)
                        imageView.setImageBitmap(getRoundedCornerBitmap(bitmap,imageView.getWidth(),imageView.getHeight()));
                else
                        imageView.setImageBitmap(bitmap);
        }
    }
   
    public void clearCache() {
        memoryCache.clear();
        fileCache.clear();
    }
   
   public Bitmap getRoundedCornerBitmap(Bitmap bitmap,int w,int h) {
           if(bitmap==null)
                   return null;
           if(w>maxRoundWidth || h>maxRoundWidth)
                   return bitmap;
           if(w<1 || h<1)
                   return bitmap;
         
           
        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_4444);
        Canvas canvas = new Canvas(output);
       


        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
        final RectF rectF = new RectF(0,0,bitmap.getWidth(), bitmap.getHeight());
        final float roundPx = 7;

        paint.setAntiAlias(true);
        canvas.drawARGB(0, 255, 255,255);
        paint.setColor(0xff424242);
        canvas.drawRoundRect(rectF, roundPx, roundPx, paint);

        paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rectF, paint);
       
       
        paint.setStyle(Style.STROKE);
        paint.setColor(Color.WHITE);
       

        paint.setStrokeWidth(2);
        paint.setAntiAlias(true);
        canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
       
        return output;             
    }
}

AsyncTask per caricare le immagini:
Codice (Java): [Seleziona]
public class ImageLoader extends AsyncTask<ImageView, Void, Bitmap> {

        ImageView imageView = null;

        @Override
        protected Bitmap doInBackground(ImageView... imageViews) {
            this.imageView = imageViews[0];
            return download_Image((String)imageView.getTag());
        }

        @Override
        protected void onPostExecute(Bitmap result) {
            //imageView.setImageBitmap(utils.getRoundedCornerBitmap(result));
                imageView.setImageBitmap(result);
        }


        private Bitmap download_Image(String url) {
          URL myFileUrl =null;          
          try {
               myFileUrl= new URL(url);
          } catch (MalformedURLException e) {
               e.printStackTrace();
               return null;
          }
          try {
               HttpURLConnection conn= (HttpURLConnection)myFileUrl.openConnection();
               conn.setDoInput(true);
               conn.connect();
               //int length = conn.getContentLength();
               InputStream is = conn.getInputStream();
               BufferedInputStream bis = new BufferedInputStream(is);
               bis.close();
               is.close();
               return BitmapFactory.decodeStream(is);
          } catch (IOException e) {
               e.printStackTrace();
               return null;
          }
        }
}

MemoryCache:
Codice (Java): [Seleziona]
import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Set;


import android.graphics.Bitmap;
import android.util.Log;

public class MemoryCache {
    private HashMap<String, SoftReference<Bitmap>> cache=new HashMap<String, SoftReference<Bitmap>>();
    private String urlNull;
   
 public Bitmap get(String id){
        if(!cache.containsKey(id))
            return null;
        SoftReference<Bitmap> ref=cache.get(id);
        return ref.get();
    }
   
   
    public void put(String id, Bitmap bitmap){
        cache.put(id, new SoftReference<Bitmap>(bitmap));
        urlNull=getUrlIfNull();
     
       
    }

    public void clear() {
       
        cache.clear();
    }
    private String getUrlIfNull()
    {
                SoftReference<Bitmap> soft = (SoftReference<Bitmap>) cache.values().toArray()[0];
        Set<String> key = cache.keySet();
        String ris="";
        for(String k : key)
        {
                String result = cache.get(k).toString();
                if(result.equalsIgnoreCase(soft.toString()))
                {
                        ris=k;
                }
                       
        }
        return ris;

    }
   
   public String getUrlNull()
   {
           return this.urlNull;
   }
 
   
}

FileCache
Codice (Java): [Seleziona]
public class FileCache {
   
    private File cacheDir;
   
    public FileCache(Context context){
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
            cacheDir=new File(Environment.getExternalStorageDirectory(),"qr");
        else
            cacheDir=context.getCacheDir();
       
        if(!cacheDir.exists())
            cacheDir.mkdirs();
    }
   
    public File getFile(String url){
        String filename=String.valueOf(url.hashCode());
        File f = new File(cacheDir, filename);
        return f;
    }
   
    public void clear(){
        File[] files=cacheDir.listFiles();
        for(File f:files)
            f.delete();
    }
}

Mi hanno consigliato di utilizzare SoftReference ma nonostante questo, quando carico molte immagini vado outOfMemory.
Inoltre ho notato che quando carico le immagini in una listview, l'imageLoader tende a ricaricarle nuovamente quando la listview ricicla gli items. Per intenderci, quando scrollo la mia Listview ho delle immagini che inizialmente sono + piccoline e poi vengono centrate (sto usando Center_crop) ed occupano tutto lo spazio disponibile. Se scrollo ancora e successivamente torno sullo stesso item, l'imageloader è come se ricaricasse nuovamente l'immagine (come prima, l'immagine inizialmente è piccolina e poi viene ingrandita). Io vorrei che una volta che l'immagine viene caricata ed ingrandita e rimanga fissa, nel senso che non ci sia + bisogno di ricaricarla. Consigli? Grazie

Offline elfo83

  • Utente normale
  • ***
  • Post: 283
  • Respect: +23
    • Mostra profilo
  • Sistema operativo:
    Mac OS 10.8.2
Re:Applicazione non risponde e outofmemory
« Risposta #1 il: 11 Luglio 2013, 23:07:21 CEST »
0
Ciao a tutti, un mio collega di lavoro mi ha consigliato di usare nella mia attività dove ho una lista con molte immagini e sulla quale posso caricarne sempre di +, invece che ImageView, SoftReferences<ImageView>. In questo modo, la vm, quando sta per andare out of memory libera le referenze. Qualcuno di voi  l'ha mai provato o è una cosa che sconsigliate di fare? Grazie

Offline iceweasel

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 878
  • Respect: +147
    • Mostra profilo
  • Dispositivo Android:
    LGE P990 - Google Nexus 5
  • Sistema operativo:
    Linux Debian Sid
Re:Applicazione non risponde e outofmemory
« Risposta #2 il: 12 Luglio 2013, 01:08:13 CEST »
0
I SoftReferences e i WeakReference hanno un comportamento particolare dalla versione 9 delle API di Android, la JVM è troppo aggressiva nei loro confronti e vengono liberati dalla memoria quasi subito.

Google consiglia di usare la LruCache:

Caching Bitmaps | Android Developers


adb logcat | tee /tmp/logcat | grep TAG

Offline elfo83

  • Utente normale
  • ***
  • Post: 283
  • Respect: +23
    • Mostra profilo
  • Sistema operativo:
    Mac OS 10.8.2
Re:Applicazione non risponde e outofmemory
« Risposta #3 il: 12 Luglio 2013, 02:00:45 CEST »
0
Si l'avevo visto grazie comunque. Qualcuno consiglia una buona libreria, eccetto universal imageloader e simply imageloader, per caricamento immagini da url + filecache + memory cache? Grazie

Offline Nicola_D

  • Moderatore
  • Utente storico
  • *****
  • Post: 2479
  • SBAGLIATO!
  • Respect: +323
    • Github
    • Google+
    • nicoladorigatti
    • Mostra profilo
  • Dispositivo Android:
    Nexus 6p, Nexus 4, Nexus S, Nexus 7(2012)
  • Sistema operativo:
    Windows 7
Re:Applicazione non risponde e outofmemory
« Risposta #4 il: 12 Luglio 2013, 10:12:21 CEST »
0
Si l'avevo visto grazie comunque. Qualcuno consiglia una buona libreria, eccetto universal imageloader e simply imageloader, per caricamento immagini da url + filecache + memory cache? Grazie
hai dato un occhio a volley?
IMPORTANTE:NON RISPONDO A PROBLEMI VIA MESSAGGIO PRIVATO
LOGCAT: Non sai cos'è? -> Android Debug Bridge | Android Developers
               Dov'è in Eclipse? -> Window -> Open Prospective -> DDMS e guarda in basso!
[Obbligatorio] Logcat, questo sconosciuto! (Gruppo AndDev.it LOGTFO) - Android Developers Italia

Offline elfo83

  • Utente normale
  • ***
  • Post: 283
  • Respect: +23
    • Mostra profilo
  • Sistema operativo:
    Mac OS 10.8.2
Re:Applicazione non risponde e outofmemory
« Risposta #5 il: 12 Luglio 2013, 16:22:36 CEST »
0
no non so cosa sia.

Offline Nicola_D

  • Moderatore
  • Utente storico
  • *****
  • Post: 2479
  • SBAGLIATO!
  • Respect: +323
    • Github
    • Google+
    • nicoladorigatti
    • Mostra profilo
  • Dispositivo Android:
    Nexus 6p, Nexus 4, Nexus S, Nexus 7(2012)
  • Sistema operativo:
    Windows 7
Re:Applicazione non risponde e outofmemory
« Risposta #6 il: 12 Luglio 2013, 17:16:44 CEST »
0
no non so cosa sia.
cerca, è molto famosa, fatta da un gruppo di dipendenti google
IMPORTANTE:NON RISPONDO A PROBLEMI VIA MESSAGGIO PRIVATO
LOGCAT: Non sai cos'è? -> Android Debug Bridge | Android Developers
               Dov'è in Eclipse? -> Window -> Open Prospective -> DDMS e guarda in basso!
[Obbligatorio] Logcat, questo sconosciuto! (Gruppo AndDev.it LOGTFO) - Android Developers Italia

Offline elfo83

  • Utente normale
  • ***
  • Post: 283
  • Respect: +23
    • Mostra profilo
  • Sistema operativo:
    Mac OS 10.8.2
Re:Applicazione non risponde e outofmemory
« Risposta #7 il: 12 Luglio 2013, 21:12:29 CEST »
0
Ciao Nicola, ho dato uno sguardo alla libreria. Per quanto riguarda tutta la parte sulla connessione e raccolta dati non ho bisogno. Non ho problemi a chiamare script e gestire risultati. Il problema sono le immagini e forse il modo in cui ho creato la memoryCache e fileCache, come puoi vedere nelle mie risposte precedenti. Diciamo che ho migliorato un pochino la gestione della memoria inserendo
Codice (Java): [Seleziona]
bmp=null;
System.gc();
subito dopo runOnUIthread nel metodo run() della classe PhotoLoader nella classe ImgLoader. In questo modo ogni volta che prendo una bitmap e la utilizzo, cancello i suoi riferimenti. In questo modo nelle listview che ho, riesco a scorrere in maniera molto + veloce e naturale senza andare fuori memoria. Se però carico tante immagini e passo da un'attivity ad un altra (considera che ho un tabhost) dopo un po' vado fuori memoria...

Offline Nicola_D

  • Moderatore
  • Utente storico
  • *****
  • Post: 2479
  • SBAGLIATO!
  • Respect: +323
    • Github
    • Google+
    • nicoladorigatti
    • Mostra profilo
  • Dispositivo Android:
    Nexus 6p, Nexus 4, Nexus S, Nexus 7(2012)
  • Sistema operativo:
    Windows 7
Re:Applicazione non risponde e outofmemory
« Risposta #8 il: 12 Luglio 2013, 21:46:07 CEST »
0
se vai in outofmemory è perchè fai troppe allocazioni, systemgc libera solo ciò che può.
guardando a caso ho visto:
image loading - Android Volley ImageLoader - BitmapLruCache parameter? - Stack Overflow

volley scarica anche immagini
IMPORTANTE:NON RISPONDO A PROBLEMI VIA MESSAGGIO PRIVATO
LOGCAT: Non sai cos'è? -> Android Debug Bridge | Android Developers
               Dov'è in Eclipse? -> Window -> Open Prospective -> DDMS e guarda in basso!
[Obbligatorio] Logcat, questo sconosciuto! (Gruppo AndDev.it LOGTFO) - Android Developers Italia

Offline elfo83

  • Utente normale
  • ***
  • Post: 283
  • Respect: +23
    • Mostra profilo
  • Sistema operativo:
    Mac OS 10.8.2
Re:Applicazione non risponde e outofmemory
« Risposta #9 il: 12 Luglio 2013, 22:52:44 CEST »
0
Quindi pensi che sia solo un problema di Caching e non di bitmap? Per quanto riguarda le bitmap sto utilizzando tutte le accortezze necessarie per non andare OOM...

Offline elfo83

  • Utente normale
  • ***
  • Post: 283
  • Respect: +23
    • Mostra profilo
  • Sistema operativo:
    Mac OS 10.8.2
Re:Applicazione non risponde e outofmemory
« Risposta #10 il: 24 Luglio 2013, 16:26:18 CEST »
0
Ho provato ad utilizzare una cacheLRU ma ho sempre lo stesso problema: quando ho molte molte immagini e scrollo le mie listView e vado da un'attività ad un altrà, la mia heap cresce a dismisura perchè credo non riesco a liberare in maniera corretta le referenze alle mie imageview. Qualcuno ha qualche altra idea? Grazie

Offline iceweasel

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 878
  • Respect: +147
    • Mostra profilo
  • Dispositivo Android:
    LGE P990 - Google Nexus 5
  • Sistema operativo:
    Linux Debian Sid
Re:Applicazione non risponde e outofmemory
« Risposta #11 il: 24 Luglio 2013, 21:19:30 CEST »
0
Si è già parlato del memory leak in altri thread. Devi guardare questo video e leggere la documentazione allegata:

http://www.google.com/events/io/2011/sessions/memory-management-for-android-apps.html

e usare questo plugin per Eclipse:

http://www.eclipse.org/mat/
adb logcat | tee /tmp/logcat | grep TAG

Offline elfo83

  • Utente normale
  • ***
  • Post: 283
  • Respect: +23
    • Mostra profilo
  • Sistema operativo:
    Mac OS 10.8.2
Re:Applicazione non risponde e outofmemory
« Risposta #12 il: 25 Luglio 2013, 00:13:24 CEST »
0
Ho scaricato mat e sto cercando di capire come funziona. Dato che sto sviluppando con una sdk 2.2 (API 8), il mio supervisore mi ha consigliato di utilizzare nelle attività in cui ho solo liste di immagini le softReference. Cioè dichiare solo le imageView, dato che sono quelle che accolgono dati "pesanti", come softReference. Ho provato ad implementarle in un paio di classi è sicuramente va già un po' meglio rispetto a prima nel senso che quando l'heap cresce, automaticamente tutte le mie referenze soft vengono eliminate e a volte ho visto un recupero da 35000k a 25000k, cioè di ben 10000k. Ora sto cercando di fare la stessa cosa in tutte quelle attività in cui ho molte immagini pesanti. Sto usando tutte le accortezze necessarie: ricycle() quando non uso + bitmap, Filecache e memory cache etc. Ho letto che dalle API 11 è sconsigliato usare SoftReference perchè la gc è molto aggressiva. Dato che sto sviluppando su API 8 ho pensato che se non uso delle softReference e non richiamo la gc manualmente, la mia applicazione rischia di andare out of memory. Che ne dite di questa soluzione?

Offline iceweasel

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 878
  • Respect: +147
    • Mostra profilo
  • Dispositivo Android:
    LGE P990 - Google Nexus 5
  • Sistema operativo:
    Linux Debian Sid
Re:Applicazione non risponde e outofmemory
« Risposta #13 il: 25 Luglio 2013, 15:43:49 CEST »
0
La versione del API che conta è quella effettiva sul telefono su cui gira il codice. Con i vecchi telefoni con Froyo i softReference in qualche modo si comportano come sulla JVM di Oracle, con Gingerbread e successivi la JVM di Android elimina quasi subito tutti gli oggetti assegnati con i softReference quando non sono più utilizzati.
adb logcat | tee /tmp/logcat | grep TAG

Offline elfo83

  • Utente normale
  • ***
  • Post: 283
  • Respect: +23
    • Mostra profilo
  • Sistema operativo:
    Mac OS 10.8.2
Re:Applicazione non risponde e outofmemory
« Risposta #14 il: 25 Luglio 2013, 17:06:25 CEST »
0
Ho capito, ma sto vedendo che dichiarare le mie imageView, nelle attività dove ho molte immagini, come softReference, è l'unico modo che funziona.