2013-04-02 13 views
11

Attualmente sto sviluppando un'applicazione che attraversa una storia. La trama contiene "scene" che contengono più file JPEG e PNG che vengono visualizzati tramite ImageViews. Creo l'ImageView e aggiungi a esso al layout tramite la seguente funzione:Problema di memoria bitmap Android - Errore: memoria esaurita su allocazione 8294416 byte

private ImageView newImage(Show show) 
{ 
    ImageView iv = new ImageView(this); 
    String filePath = comin.generateFilePath(show); 
    Log.i(TAG, "newImage, filePath = " + filePath + " id = " + show.id); 
    WeakReference<Bitmap> bmp = new WeakReference<Bitmap>(scaleBitmap(filePath)); //added 4/1/13 
    //Bitmap bmp = scaleBitmap(filePath); 
    Log.i(TAG, "newImage, width = " + bmp.get().getWidth() + ", height = " + bmp.get().getHeight()); 
    iv.setImageBitmap(bmp.get()); 
    iv.setScaleType(ImageView.ScaleType.FIT_XY); 
    iv.setId(show.id); 

    //set visibility 
    if (show.visible) 
     iv.setVisibility(View.VISIBLE); 
    else 
     iv.setVisibility(View.INVISIBLE); 

    //set dimensions 
    int width = (app.getWidth() * show.dimX)/100; 
    int height = (app.getHeight() * show.dimY)/100; 
    RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(width, height); 
    iv.setLayoutParams(rlp); 

    return iv; 
} 

Una volta che la scena è finita, ho poi chiaro tutti i ImageViews tranne uno, che non sono disponibili immagini e serve solo ad ascoltare per il tocco eventi.

private void clearScene(boolean clearTouch) 
{ 
    RelativeLayout parent = (RelativeLayout) findViewById(R.id.relative_layout); 
    logMemory("clearScene, START"); 

    int count = parent.getChildCount(); 
    for (int a = count - 1; a >= 0; a--) 
    { 
     int id = parent.getChildAt(a).getId(); 
     String message = "clearScene id = " + id + ", count = " + count + ", a = " + a; 
     if (id == TOUCH_VIEW_ID && !clearTouch) 
     { 
      message = message + ", ignore touch screen view"; 
     } 
     else 
     { 
      unbindView(parent.getChildAt(a)); 
      parent.getChildAt(a).clearAnimation(); 
      parent.removeView(parent.getChildAt(a)); 
      message = message + ", unbindView, clearAnimation, removeView"; 
     } 
     Log.i(TAG, message); 
     logMemory("clearScene, CLEARED VIEW"); 
    } 

    handler.removeCallbacksAndMessages(null); //stop any future scheduled tasks from triggering 
    logMemory("clearScene, BEFORE TRASH COLLECTOR"); 
    System.gc(); 
    logMemory("clearScene, AFTER TRASH COLLECTOR"); 
} 

Come potete vedere, chiamo il metodo unbindView(), per cercare di cancellare qualsiasi tipo di possibile perdita di memoria.

private void unbindView(View view) 
{ 
    String message = "unbindView, id = " + view.getId(); 
    try {view.setOnClickListener(null);} catch (Throwable mayHappen) {}; 
    try {view.setOnCreateContextMenuListener(null);} catch (Throwable mayHappen) {}; 
    try {view.setOnFocusChangeListener(null);} catch (Throwable mayHappen) {}; 
    try {view.setOnKeyListener(null);} catch (Throwable mayHappen) {}; 
    try {view.setOnLongClickListener(null);} catch (Throwable mayHappen) {}; 
    try {view.setOnClickListener(null);} catch (Throwable mayHappen) {}; 

    if (view.getBackground() != null) 
    { 
     message = message + ", setBackgroundCallback(null)"; 
     view.getBackground().setCallback(null); 
    } 

    if (view instanceof ImageView) 
    { 
     if (((ImageView)view).getDrawable() != null) 
     { 
      if (((ImageView)view).getDrawable() instanceof BitmapDrawable) 
      { 
       message = message + ", recycle bitmap"; 
       ((BitmapDrawable)((ImageView)view).getDrawable()).getBitmap().recycle(); 
      } 
      message = message + ", setDrawableCallback(null)"; 
      ((ImageView)view).getDrawable().setCallback(null); 
     } 
     message = message + ", setImageBitmap(null), setBackgroundDrawable(null)"; 
     ((ImageView) view).setImageBitmap(null); 
     ((ImageView) view).setBackgroundDrawable(null); 
    } 
    Log.i(TAG, message); 
} 

volta che tutti i ImageViews sono illimitato, ho poi eseguito il garbage collector nella funzione clearScene.

*** EDIT (4/2/13) OK, dopo alcune ricerche e prove ed errori, ho modificato la registrazione della memoria. Ecco i metodi rilevanti:

In onResume(), ho impostato un valore booleano su true a seconda della versione di Android (per determinare se utilizza la memoria nativa o Java per Bitmap), e quindi inizializzo il valore predefinito di 0 per i vecchi valori della memoria;

@Override 
protected void onResume() 
{ 
    super.onResume(); 

    if (android.os.Build.VERSION.SDK_INT >= 11) debugJavaMemory = true; 
    else debugNativeMemory = true; 
    availableJavaMemoryOld = 0; 
    availableNativeMemoryOld = 0; 
    dialogDebug(); 
} 

Questa è la mia funzione di registrazione. Registra a seconda se la versione corrente di Android utilizza memoria nativa o Java per archiviare Bitmap.

private void logMemory(String callingFunction) 
{ 
    if (debugJavaMemory) 
    { 
     long max = Runtime.getRuntime().maxMemory()/1024; 
     long used = Runtime.getRuntime().totalMemory()/1024; 
     long available = max - used; 
     long change = available - availableJavaMemoryOld; 
     if (availableJavaMemoryOld != 0) 
      Log.i(TAG_MEMORY, "jMEM M:" + max + ", U:" + used + ", A:" + available + ", C:" + change + ", " + callingFunction); 
     availableJavaMemoryOld = available; 
    } 
    else if (debugNativeMemory) 
    { 
     long max = Debug.getNativeHeapSize()/1024; 
     long used = Debug.getNativeHeapAllocatedSize()/1024; 
     long available = max - used; 
     long change = available - availableNativeMemoryOld; 
     if (availableNativeMemoryOld != 0) 
      Log.i(TAG_MEMORY, "nMEM M:" + max + ", U:" + used + ", A:" + available + ", C:" + change + ", " + callingFunction); 
     availableNativeMemoryOld = available; 
    } 
} 

Se guardate il mio registro raccolgo da un emulatore in esecuzione Android 10 (2.3.3), il garbage collector sembra funzionare perfettamente! L'unica cosa che ho notato è strano, è che la memoria nativa massima potrebbe aumentare dinamicamente !?

Legenda: M: (memoria massima), U: (memoria utilizzata), A: (memoria disponibile), C: (cambio di memoria disponibile), funzione che ha chiamato la funzione di log

04-03 02:34:20.758: I/MEMORY(1045): nMEM M:18336, U:13287, A:5049, C:-2549, loadScene, ADDED IMAGE b:0, s:0, id:0 
04-03 02:34:21.267: I/MEMORY(1045): nMEM M:21568, U:21391, A:177, C:-4872, loadScene, ADDED IMAGE b:0, s:0, id:1 
04-03 02:34:35.227: I/MEMORY(1045): nMEM M:21568, U:13288, A:8280, C:8103, clearScene, CLEARED VIEW id:1 
04-03 02:34:35.267: I/MEMORY(1045): nMEM M:21568, U:5184, A:16384, C:8104, clearScene, CLEARED VIEW id:0 
04-03 02:34:35.327: I/MEMORY(1045): nMEM M:21568, U:4977, A:16591, C:207, clearScene, AFTER TRASH COLLECTOR 
04-03 02:34:36.067: I/MEMORY(1045): nMEM M:21568, U:13082, A:8486, C:-8105, loadScene, ADDED IMAGE b:1, s:0, id:0 
04-03 02:34:47.177: I/MEMORY(1045): nMEM M:21568, U:4979, A:16589, C:8103, clearScene, CLEARED VIEW id:0 
04-03 02:34:47.277: I/MEMORY(1045): nMEM M:21568, U:4978, A:16590, C:1, clearScene, AFTER TRASH COLLECTOR 
04-03 02:34:47.997: I/MEMORY(1045): nMEM M:21568, U:13082, A:8486, C:-8104, loadScene, ADDED IMAGE b:1, s:1, id:0 
04-03 02:34:49.307: I/MEMORY(1045): nMEM M:26224, U:21186, A:5038, C:-3448, loadScene, ADDED IMAGE b:1, s:1, id:1 
04-03 02:34:50.597: I/MEMORY(1045): nMEM M:34328, U:29290, A:5038, C:0, loadScene, ADDED IMAGE b:1, s:1, id:2 
04-03 02:34:51.839: I/MEMORY(1045): nMEM M:42432, U:37395, A:5037, C:-1, loadScene, ADDED IMAGE b:1, s:1, id:3 
04-03 02:35:00.377: I/MEMORY(1045): nMEM M:42432, U:29293, A:13139, C:8102, clearScene, CLEARED VIEW id:3 
04-03 02:35:00.387: I/MEMORY(1045): nMEM M:42432, U:21189, A:21243, C:8104, clearScene, CLEARED VIEW id:2 
04-03 02:35:00.397: I/MEMORY(1045): nMEM M:42432, U:13085, A:29347, C:8104, clearScene, CLEARED VIEW id:1 
04-03 02:35:00.407: I/MEMORY(1045): nMEM M:42432, U:4982, A:37450, C:8103, clearScene, CLEARED VIEW id:0 
04-03 02:35:00.449: I/MEMORY(1045): nMEM M:42432, U:4978, A:37454, C:4, clearScene, AFTER TRASH COLLECTOR 
04-03 02:35:01.217: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:-8105, loadScene, ADDED IMAGE b:1, s:2, id:0 
04-03 02:35:23.458: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:8104, clearScene, CLEARED VIEW id:0 
04-03 02:35:23.508: I/MEMORY(1045): nMEM M:42432, U:4978, A:37454, C:1, clearScene, AFTER TRASH COLLECTOR 
04-03 02:35:24.777: I/MEMORY(1045): nMEM M:42432, U:13082, A:29350, C:-8104, loadScene, ADDED IMAGE b:1, s:3, id:0 
04-03 02:35:25.719: I/MEMORY(1045): nMEM M:42432, U:21186, A:21246, C:-8104, loadScene, ADDED IMAGE b:1, s:3, id:1 
04-03 02:35:26.457: I/MEMORY(1045): nMEM M:42432, U:29291, A:13141, C:-8105, loadScene, ADDED IMAGE b:1, s:3, id:2 
04-03 02:35:55.008: I/MEMORY(1045): nMEM M:42432, U:21187, A:21245, C:8104, clearScene, CLEARED VIEW id:2 
04-03 02:35:55.027: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:8104, clearScene, CLEARED VIEW id:1 
04-03 02:35:55.037: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:8104, clearScene, CLEARED VIEW id:0 
04-03 02:35:55.077: I/MEMORY(1045): nMEM M:42432, U:4978, A:37454, C:1, clearScene, AFTER TRASH COLLECTOR 
04-03 02:35:55.829: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:-8105, loadScene, ADDED IMAGE b:1, s:4, id:0 
04-03 02:35:56.427: I/MEMORY(1045): nMEM M:42432, U:21187, A:21245, C:-8104, loadScene, ADDED IMAGE b:1, s:4, id:1 
04-03 02:36:00.257: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:8104, clearScene, CLEARED VIEW id:1 
04-03 02:36:00.278: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:8104, clearScene, CLEARED VIEW id:0 
04-03 02:36:00.318: I/MEMORY(1045): nMEM M:42432, U:4978, A:37454, C:1, clearScene, AFTER TRASH COLLECTOR 
04-03 02:36:01.687: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:-8105, loadScene, ADDED IMAGE b:1, s:5, id:0 
04-03 02:36:06.437: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:8104, clearScene, CLEARED VIEW id:0 
04-03 02:36:06.487: I/MEMORY(1045): nMEM M:42432, U:4978, A:37454, C:1, clearScene, AFTER TRASH COLLECTOR 
04-03 02:36:07.777: I/MEMORY(1045): nMEM M:42432, U:13082, A:29350, C:-8104, loadScene, ADDED IMAGE b:1, s:6, id:0 
04-03 02:36:09.297: I/MEMORY(1045): nMEM M:42432, U:4978, A:37454, C:8104, clearScene, CLEARED VIEW id:0 
04-03 02:36:09.337: I/MEMORY(1045): nMEM M:42432, U:4978, A:37454, C:0, clearScene, AFTER TRASH COLLECTOR 
04-03 02:36:10.727: I/MEMORY(1045): nMEM M:42432, U:13082, A:29350, C:-8104, loadScene, ADDED IMAGE b:1, s:7, id:0 
04-03 02:36:20.947: I/MEMORY(1045): nMEM M:42432, U:4978, A:37454, C:8104, clearScene, CLEARED VIEW id:0 
04-03 02:36:20.987: I/MEMORY(1045): nMEM M:42432, U:4978, A:37454, C:0, clearScene, AFTER TRASH COLLECTOR 
04-03 02:36:22.367: I/MEMORY(1045): nMEM M:42432, U:13082, A:29350, C:-8104, loadScene, ADDED IMAGE b:1, s:8, id:0 
04-03 02:36:23.317: I/MEMORY(1045): nMEM M:42432, U:21187, A:21245, C:-8105, loadScene, ADDED IMAGE b:1, s:8, id:1 
04-03 02:36:23.887: I/MEMORY(1045): nMEM M:42432, U:29291, A:13141, C:-8104, loadScene, ADDED IMAGE b:1, s:8, id:2 
04-03 02:36:26.507: I/MEMORY(1045): nMEM M:42432, U:21187, A:21245, C:8104, clearScene, CLEARED VIEW id:2 
04-03 02:36:26.517: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:8104, clearScene, CLEARED VIEW id:1 
04-03 02:36:26.527: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:8104, clearScene, CLEARED VIEW id:0 
04-03 02:36:26.577: I/MEMORY(1045): nMEM M:42432, U:4978, A:37454, C:1, clearScene, AFTER TRASH COLLECTOR 
04-03 02:36:27.797: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:-8105, loadScene, ADDED IMAGE b:1, s:9, id:0 
04-03 02:36:29.248: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:8104, clearScene, CLEARED VIEW id:0 
04-03 02:36:29.287: I/MEMORY(1045): nMEM M:42432, U:4978, A:37454, C:1, clearScene, AFTER TRASH COLLECTOR 
04-03 02:36:30.547: I/MEMORY(1045): nMEM M:42432, U:13082, A:29350, C:-8104, loadScene, ADDED IMAGE b:1, s:10, id:0 
04-03 02:36:32.177: I/MEMORY(1045): nMEM M:42432, U:4978, A:37454, C:8104, clearScene, CLEARED VIEW id:0 
04-03 02:36:32.228: I/MEMORY(1045): nMEM M:42432, U:4978, A:37454, C:0, clearScene, AFTER TRASH COLLECTOR 
04-03 02:36:33.467: I/MEMORY(1045): nMEM M:42432, U:13082, A:29350, C:-8104, loadScene, ADDED IMAGE b:1, s:11, id:0 
04-03 02:36:33.977: I/MEMORY(1045): nMEM M:42432, U:21187, A:21245, C:-8105, loadScene, ADDED IMAGE b:1, s:11, id:1 
04-03 02:36:34.527: I/MEMORY(1045): nMEM M:42432, U:29291, A:13141, C:-8104, loadScene, ADDED IMAGE b:1, s:11, id:2 
04-03 02:36:35.058: I/MEMORY(1045): nMEM M:42432, U:37395, A:5037, C:-8104, loadScene, ADDED IMAGE b:1, s:11, id:3 
04-03 02:36:41.260: I/MEMORY(1045): nMEM M:42432, U:29291, A:13141, C:8104, clearScene, CLEARED VIEW id:3 
04-03 02:36:41.267: I/MEMORY(1045): nMEM M:42432, U:21187, A:21245, C:8104, clearScene, CLEARED VIEW id:2 
04-03 02:36:41.278: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:8104, clearScene, CLEARED VIEW id:1 
04-03 02:36:41.287: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:8104, clearScene, CLEARED VIEW id:0 
04-03 02:36:41.337: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:0, clearScene, AFTER TRASH COLLECTOR 
04-03 02:36:42.618: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:-8104, loadScene, ADDED IMAGE b:2, s:0, id:0 
04-03 02:37:00.550: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:8104, clearScene, CLEARED VIEW id:0 
04-03 02:37:00.587: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:0, clearScene, AFTER TRASH COLLECTOR 
04-03 02:37:01.817: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:-8104, loadScene, ADDED IMAGE b:2, s:1, id:0 
04-03 02:37:03.347: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:8104, clearScene, CLEARED VIEW id:0 
04-03 02:37:03.397: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:0, clearScene, AFTER TRASH COLLECTOR 
04-03 02:37:04.607: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:-8104, loadScene, ADDED IMAGE b:2, s:2, id:0 
04-03 02:37:05.258: I/MEMORY(1045): nMEM M:42432, U:21187, A:21245, C:-8104, loadScene, ADDED IMAGE b:2, s:2, id:1 
04-03 02:37:07.677: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:8104, clearScene, CLEARED VIEW id:1 
04-03 02:37:07.687: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:8104, clearScene, CLEARED VIEW id:0 
04-03 02:37:07.737: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:0, clearScene, AFTER TRASH COLLECTOR 
04-03 02:37:09.017: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:-8104, loadScene, ADDED IMAGE b:2, s:3, id:0 
04-03 02:37:10.327: I/MEMORY(1045): nMEM M:42432, U:21187, A:21245, C:-8104, loadScene, ADDED IMAGE b:2, s:3, id:1 
04-03 02:37:13.330: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:8104, clearScene, CLEARED VIEW id:1 
04-03 02:37:13.337: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:8104, clearScene, CLEARED VIEW id:0 
04-03 02:37:13.387: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:0, clearScene, AFTER TRASH COLLECTOR 
04-03 02:37:14.697: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:-8104, loadScene, ADDED IMAGE b:2, s:4, id:0 
04-03 02:37:16.037: I/MEMORY(1045): nMEM M:42432, U:21187, A:21245, C:-8104, loadScene, ADDED IMAGE b:2, s:4, id:1 
04-03 02:37:17.367: I/MEMORY(1045): nMEM M:42432, U:29292, A:13140, C:-8105, loadScene, ADDED IMAGE b:2, s:4, id:2 
04-03 02:37:19.087: I/MEMORY(1045): nMEM M:42432, U:37396, A:5036, C:-8104, loadScene, ADDED IMAGE b:2, s:4, id:3 
04-03 02:37:44.347: I/MEMORY(1045): nMEM M:42432, U:29293, A:13139, C:8103, clearScene, CLEARED VIEW id:3 
04-03 02:37:44.357: I/MEMORY(1045): nMEM M:42432, U:21189, A:21243, C:8104, clearScene, CLEARED VIEW id:2 
04-03 02:37:44.367: I/MEMORY(1045): nMEM M:42432, U:13085, A:29347, C:8104, clearScene, CLEARED VIEW id:1 
04-03 02:37:44.377: I/MEMORY(1045): nMEM M:42432, U:4981, A:37451, C:8104, clearScene, CLEARED VIEW id:0 
04-03 02:37:44.437: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:2, clearScene, AFTER TRASH COLLECTOR 
04-03 02:37:45.667: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:-8104, loadScene, ADDED IMAGE b:2, s:5, id:0 
04-03 02:37:46.917: I/MEMORY(1045): nMEM M:42432, U:21188, A:21244, C:-8105, loadScene, ADDED IMAGE b:2, s:5, id:1 
04-03 02:37:48.167: I/MEMORY(1045): nMEM M:42432, U:29292, A:13140, C:-8104, loadScene, ADDED IMAGE b:2, s:5, id:2 
04-03 02:37:49.807: I/MEMORY(1045): nMEM M:42432, U:37396, A:5036, C:-8104, loadScene, ADDED IMAGE b:2, s:5, id:3 
04-03 02:38:08.239: I/MEMORY(1045): nMEM M:42432, U:29293, A:13139, C:8103, clearScene, CLEARED VIEW id:3 
04-03 02:38:08.258: I/MEMORY(1045): nMEM M:42432, U:21189, A:21243, C:8104, clearScene, CLEARED VIEW id:2 
04-03 02:38:08.267: I/MEMORY(1045): nMEM M:42432, U:13086, A:29346, C:8103, clearScene, CLEARED VIEW id:1 
04-03 02:38:08.277: I/MEMORY(1045): nMEM M:42432, U:4982, A:37450, C:8104, clearScene, CLEARED VIEW id:0 
04-03 02:38:08.317: I/MEMORY(1045): nMEM M:42432, U:4979, A:37453, C:3, clearScene, AFTER TRASH COLLECTOR 
04-03 02:38:09.527: I/MEMORY(1045): nMEM M:42432, U:13083, A:29349, C:-8104, loadScene, ADDED IMAGE b:2, s:6, id:0 

Come accennato , la memoria viene pulita dopo che ImageView non è associato!

Ecco il log che ho raccolto dal mio Nexus 7 rotto con Android 17 (4.2). È davvero difficile capire come viene utilizzata la memoria qui. Non è mai coerente! A volte la memoria non viene allocata quando carico ImageView. A volte la memoria viene cancellata solo quando carico un nuovo ImageView.

Legenda: M: (memoria massima), U: (memoria utilizzata), A: (memoria disponibile), C: (cambio di memoria disponibile), funzione che ha chiamato la funzione di log

04-02 22:37:05.866: I/MEMORY(15827): jMEM M:65536, U:21300, A:44236, C:0, loadScene, ADDED IMAGE b:0, s:0, id:0 
04-02 22:37:06.136: I/MEMORY(15827): jMEM M:65536, U:29444, A:36092, C:-8144, loadScene, ADDED IMAGE b:0, s:0, id:1 
04-02 22:37:19.806: I/MEMORY(15827): jMEM M:65536, U:29432, A:36104, C:12, clearScene, CLEARED VIEW id:1 
04-02 22:37:19.806: I/MEMORY(15827): jMEM M:65536, U:29432, A:36104, C:0, clearScene, CLEARED VIEW id:0 
04-02 22:37:19.836: I/MEMORY(15827): jMEM M:65536, U:29432, A:36104, C:0, clearScene, AFTER TRASH COLLECTOR 
04-02 22:37:20.116: I/MEMORY(15827): jMEM M:65536, U:37536, A:28000, C:-8104, loadScene, ADDED IMAGE b:1, s:0, id:0 
04-02 22:37:28.456: I/MEMORY(15827): jMEM M:65536, U:37532, A:28004, C:4, clearScene, CLEARED VIEW id:0 
04-02 22:37:28.486: I/MEMORY(15827): jMEM M:65536, U:37532, A:28004, C:0, clearScene, AFTER TRASH COLLECTOR 
04-02 22:37:28.756: I/MEMORY(15827): jMEM M:65536, U:37532, A:28004, C:0, loadScene, ADDED IMAGE b:1, s:1, id:0 
04-02 22:37:29.226: I/MEMORY(15827): jMEM M:65536, U:37532, A:28004, C:0, loadScene, ADDED IMAGE b:1, s:1, id:1 
04-02 22:37:29.706: I/MEMORY(15827): jMEM M:65536, U:45636, A:19900, C:-8104, loadScene, ADDED IMAGE b:1, s:1, id:2 
04-02 22:37:30.156: I/MEMORY(15827): jMEM M:65536, U:53740, A:11796, C:-8104, loadScene, ADDED IMAGE b:1, s:1, id:3 
04-02 22:37:38.676: I/MEMORY(15827): jMEM M:65536, U:53732, A:11804, C:8, clearScene, CLEARED VIEW id:3 
04-02 22:37:38.676: I/MEMORY(15827): jMEM M:65536, U:53732, A:11804, C:0, clearScene, CLEARED VIEW id:2 
04-02 22:37:38.676: I/MEMORY(15827): jMEM M:65536, U:53732, A:11804, C:0, clearScene, CLEARED VIEW id:1 
04-02 22:37:38.676: I/MEMORY(15827): jMEM M:65536, U:53732, A:11804, C:0, clearScene, CLEARED VIEW id:0 
04-02 22:37:38.696: I/MEMORY(15827): jMEM M:65536, U:53732, A:11804, C:0, clearScene, AFTER TRASH COLLECTOR 
04-02 22:37:38.966: I/MEMORY(15827): jMEM M:65536, U:53732, A:11804, C:0, loadScene, ADDED IMAGE b:1, s:2, id:0 
04-02 22:37:48.156: I/MEMORY(15827): jMEM M:65536, U:53732, A:11804, C:0, clearScene, CLEARED VIEW id:0 
04-02 22:37:48.216: I/MEMORY(15827): jMEM M:65536, U:37532, A:28004, C:16200, clearScene, AFTER TRASH COLLECTOR 
04-02 22:37:48.676: I/MEMORY(15827): jMEM M:65536, U:37532, A:28004, C:0, loadScene, ADDED IMAGE b:1, s:3, id:0 
04-02 22:37:49.256: I/MEMORY(15827): jMEM M:65536, U:37532, A:28004, C:0, loadScene, ADDED IMAGE b:1, s:3, id:1 
04-02 22:37:49.716: I/MEMORY(15827): jMEM M:65536, U:45636, A:19900, C:-8104, loadScene, ADDED IMAGE b:1, s:3, id:2 
04-02 22:38:07.426: I/MEMORY(15827): jMEM M:65536, U:45632, A:19904, C:4, clearScene, CLEARED VIEW id:2 
04-02 22:38:07.426: I/MEMORY(15827): jMEM M:65536, U:45632, A:19904, C:0, clearScene, CLEARED VIEW id:1 
04-02 22:38:07.426: I/MEMORY(15827): jMEM M:65536, U:45632, A:19904, C:0, clearScene, CLEARED VIEW id:0 
04-02 22:38:07.496: I/MEMORY(15827): jMEM M:65536, U:45632, A:19904, C:0, clearScene, AFTER TRASH COLLECTOR 
04-02 22:38:07.766: I/MEMORY(15827): jMEM M:65536, U:45632, A:19904, C:0, loadScene, ADDED IMAGE b:1, s:4, id:0 
04-02 22:38:08.096: I/MEMORY(15827): jMEM M:65536, U:53736, A:11800, C:-8104, loadScene, ADDED IMAGE b:1, s:4, id:1 
04-02 22:38:10.896: I/MEMORY(15827): jMEM M:65536, U:53736, A:11800, C:0, clearScene, CLEARED VIEW id:1 
04-02 22:38:10.896: I/MEMORY(15827): jMEM M:65536, U:53736, A:11800, C:0, clearScene, CLEARED VIEW id:0 
04-02 22:38:10.916: I/MEMORY(15827): jMEM M:65536, U:53736, A:11800, C:0, clearScene, AFTER TRASH COLLECTOR 
04-02 22:38:11.436: I/MEMORY(15827): jMEM M:65536, U:53736, A:11800, C:0, loadScene, ADDED IMAGE b:1, s:5, id:0 
04-02 22:38:19.356: I/MEMORY(15827): jMEM M:65536, U:53732, A:11804, C:4, clearScene, CLEARED VIEW id:0 
04-02 22:38:19.386: I/MEMORY(15827): jMEM M:65536, U:45632, A:19904, C:8100, clearScene, AFTER TRASH COLLECTOR 
04-02 22:38:19.866: I/MEMORY(15827): jMEM M:65536, U:45632, A:19904, C:0, loadScene, ADDED IMAGE b:1, s:6, id:0 
04-02 22:38:21.326: I/MEMORY(15827): jMEM M:65536, U:45632, A:19904, C:0, clearScene, CLEARED VIEW id:0 
04-02 22:38:21.356: I/MEMORY(15827): jMEM M:65536, U:21300, A:44236, C:24332, clearScene, AFTER TRASH COLLECTOR 
04-02 22:38:21.906: I/MEMORY(15827): jMEM M:65536, U:29404, A:36132, C:-8104, loadScene, ADDED IMAGE b:1, s:7, id:0 
04-02 22:38:24.376: I/MEMORY(15827): jMEM M:65536, U:29404, A:36132, C:0, clearScene, CLEARED VIEW id:0 
04-02 22:38:24.406: I/MEMORY(15827): jMEM M:65536, U:29404, A:36132, C:0, clearScene, AFTER TRASH COLLECTOR 
04-02 22:38:24.916: I/MEMORY(15827): jMEM M:65536, U:29404, A:36132, C:0, loadScene, ADDED IMAGE b:1, s:8, id:0 
04-02 22:38:25.496: I/MEMORY(15827): jMEM M:65536, U:37548, A:27988, C:-8144, loadScene, ADDED IMAGE b:1, s:8, id:1 
04-02 22:38:25.796: I/MEMORY(15827): jMEM M:65536, U:45652, A:19884, C:-8104, loadScene, ADDED IMAGE b:1, s:8, id:2 
04-02 22:38:28.356: I/MEMORY(15827): jMEM M:65536, U:45652, A:19884, C:0, clearScene, CLEARED VIEW id:2 
04-02 22:38:28.356: I/MEMORY(15827): jMEM M:65536, U:45652, A:19884, C:0, clearScene, CLEARED VIEW id:1 
04-02 22:38:28.356: I/MEMORY(15827): jMEM M:65536, U:45652, A:19884, C:0, clearScene, CLEARED VIEW id:0 
04-02 22:38:28.376: I/MEMORY(15827): jMEM M:65536, U:45652, A:19884, C:0, clearScene, AFTER TRASH COLLECTOR 
04-02 22:38:28.846: I/MEMORY(15827): jMEM M:65536, U:45652, A:19884, C:0, loadScene, ADDED IMAGE b:1, s:9, id:0 
04-02 22:38:29.926: I/MEMORY(15827): jMEM M:65536, U:45652, A:19884, C:0, clearScene, CLEARED VIEW id:0 
04-02 22:38:29.956: I/MEMORY(15827): jMEM M:65536, U:29400, A:36136, C:16252, clearScene, AFTER TRASH COLLECTOR 
04-02 22:38:30.416: I/MEMORY(15827): jMEM M:65536, U:29400, A:36136, C:0, loadScene, ADDED IMAGE b:1, s:10, id:0 
04-02 22:38:31.446: I/MEMORY(15827): jMEM M:65536, U:29400, A:36136, C:0, clearScene, CLEARED VIEW id:0 
04-02 22:38:31.476: I/MEMORY(15827): jMEM M:65536, U:21300, A:44236, C:8100, clearScene, AFTER TRASH COLLECTOR 
04-02 22:38:31.966: I/MEMORY(15827): jMEM M:65536, U:29404, A:36132, C:-8104, loadScene, ADDED IMAGE b:1, s:11, id:0 
04-02 22:38:32.226: I/MEMORY(15827): jMEM M:65536, U:37548, A:27988, C:-8144, loadScene, ADDED IMAGE b:1, s:11, id:1 
04-02 22:38:32.526: I/MEMORY(15827): jMEM M:65536, U:45652, A:19884, C:-8104, loadScene, ADDED IMAGE b:1, s:11, id:2 
04-02 22:38:32.816: I/MEMORY(15827): jMEM M:65536, U:53756, A:11780, C:-8104, loadScene, ADDED IMAGE b:1, s:11, id:3 
04-02 22:38:34.396: I/MEMORY(15827): jMEM M:65536, U:53756, A:11780, C:0, clearScene, CLEARED VIEW id:3 
04-02 22:38:34.396: I/MEMORY(15827): jMEM M:65536, U:53756, A:11780, C:0, clearScene, CLEARED VIEW id:2 
04-02 22:38:34.396: I/MEMORY(15827): jMEM M:65536, U:53756, A:11780, C:0, clearScene, CLEARED VIEW id:1 
04-02 22:38:34.396: I/MEMORY(15827): jMEM M:65536, U:53756, A:11780, C:0, clearScene, CLEARED VIEW id:0 
04-02 22:38:34.426: I/MEMORY(15827): jMEM M:65536, U:53756, A:11780, C:0, clearScene, AFTER TRASH COLLECTOR 
04-02 22:38:34.886: I/MEMORY(15827): jMEM M:65536, U:53756, A:11780, C:0, loadScene, ADDED IMAGE b:2, s:0, id:0 
04-02 22:38:35.776: I/MEMORY(15827): jMEM M:65536, U:53756, A:11780, C:0, clearScene, CLEARED VIEW id:0 
04-02 22:38:35.816: I/MEMORY(15827): jMEM M:65536, U:21300, A:44236, C:32456, clearScene, AFTER TRASH COLLECTOR 
04-02 22:38:36.256: I/MEMORY(15827): jMEM M:65536, U:29404, A:36132, C:-8104, loadScene, ADDED IMAGE b:2, s:1, id:0 
04-02 22:38:36.976: I/MEMORY(15827): jMEM M:65536, U:29404, A:36132, C:0, clearScene, CLEARED VIEW id:0 
04-02 22:38:37.006: I/MEMORY(15827): jMEM M:65536, U:29404, A:36132, C:0, clearScene, AFTER TRASH COLLECTOR 
04-02 22:38:37.436: I/MEMORY(15827): jMEM M:65536, U:29404, A:36132, C:0, loadScene, ADDED IMAGE b:2, s:2, id:0 
04-02 22:38:37.816: I/MEMORY(15827): jMEM M:65536, U:37548, A:27988, C:-8144, loadScene, ADDED IMAGE b:2, s:2, id:1 
04-02 22:38:44.986: I/MEMORY(15827): jMEM M:65536, U:37532, A:28004, C:16, clearScene, CLEARED VIEW id:1 
04-02 22:38:44.986: I/MEMORY(15827): jMEM M:65536, U:37532, A:28004, C:0, clearScene, CLEARED VIEW id:0 
04-02 22:38:45.016: I/MEMORY(15827): jMEM M:65536, U:37532, A:28004, C:0, clearScene, AFTER TRASH COLLECTOR 
04-02 22:38:45.496: I/MEMORY(15827): jMEM M:65536, U:37532, A:28004, C:0, loadScene, ADDED IMAGE b:2, s:3, id:0 
04-02 22:38:45.996: I/MEMORY(15827): jMEM M:65536, U:45636, A:19900, C:-8104, loadScene, ADDED IMAGE b:2, s:3, id:1 
04-02 22:38:48.306: I/MEMORY(15827): jMEM M:65536, U:45636, A:19900, C:0, clearScene, CLEARED VIEW id:1 
04-02 22:38:48.306: I/MEMORY(15827): jMEM M:65536, U:45636, A:19900, C:0, clearScene, CLEARED VIEW id:0 
04-02 22:38:48.336: I/MEMORY(15827): jMEM M:65536, U:45636, A:19900, C:0, clearScene, AFTER TRASH COLLECTOR 
04-02 22:38:48.846: I/MEMORY(15827): jMEM M:65536, U:45636, A:19900, C:0, loadScene, ADDED IMAGE b:2, s:4, id:0 
04-02 22:38:49.326: I/MEMORY(15827): jMEM M:65536, U:45636, A:19900, C:0, loadScene, ADDED IMAGE b:2, s:4, id:1 
04-02 22:38:49.856: I/MEMORY(15827): jMEM M:65536, U:53740, A:11796, C:-8104, loadScene, ADDED IMAGE b:2, s:4, id:2 
04-02 22:38:50.386: I/MEMORY(15827): jMEM M:65536, U:61844, A:3692, C:-8104, loadScene, ADDED IMAGE b:2, s:4, id:3 
04-02 22:38:59.486: I/MEMORY(15827): jMEM M:65536, U:61832, A:3704, C:12, clearScene, CLEARED VIEW id:3 
04-02 22:38:59.486: I/MEMORY(15827): jMEM M:65536, U:61832, A:3704, C:0, clearScene, CLEARED VIEW id:2 
04-02 22:38:59.486: I/MEMORY(15827): jMEM M:65536, U:61832, A:3704, C:0, clearScene, CLEARED VIEW id:1 
04-02 22:38:59.486: I/MEMORY(15827): jMEM M:65536, U:61832, A:3704, C:0, clearScene, CLEARED VIEW id:0 
04-02 22:38:59.516: I/MEMORY(15827): jMEM M:65536, U:61832, A:3704, C:0, clearScene, AFTER TRASH COLLECTOR 
04-02 22:38:59.936: I/MEMORY(15827): jMEM M:65536, U:61832, A:3704, C:0, loadScene, ADDED IMAGE b:2, s:5, id:0 
04-02 22:39:00.356: I/MEMORY(15827): jMEM M:65536, U:61832, A:3704, C:0, loadScene, ADDED IMAGE b:2, s:5, id:1 

I' ve stato attraverso la formazione "Visualizzazione Bitmap effettivamente" a
http://developer.android.com/training/displaying-bitmaps/index.html

sono stato anche attraverso le seguenti domande StackOverflow:
Recycle ImageView's Bitmap
ImageView: automatically recycle bitmap if ImageView is not visible (within ScrollView)
android - out of memory exception when creating bitmap
Bitmap decodeStream OutOfMemory Exception
Detect application heap size in Android
android createBitmap OOM when ((freeMemory > bitmapSize) && (nativeFreeHeap < bitmap size))
android 495KB image taking 10MB of Heap size
Android ImageView setImageBitmap
Android Memory Leak solution
Android custom view Bitmap memory leak

e molti molti altri articoli in tutto il web!

Per chiarire, questo sembra accadere solo nel mio Nexus 7. Non ho riscontrato il problema sul mio emulatore o sul mio Galaxy Nexus. Penso che questo possa essere dovuto al fatto che sto ridimensionando le immagini.

Per favore aiutami a capire dove si trova la perdita di memoria!

*** EDIT (4/2/13) Aiutatemi a identificare il motivo per cui i registri di un emulatore con Android 10 (2.3.3) mostrano il sistema che alloca la memoria e la garbage che si schiarisce esattamente come dovrebbe, e i log del mio Nexus 7 con Android 17 (4.2) mostrano il sistema che alloca la memoria e il garbage collector che cancella la memoria apparentemente a caso?

+0

+1 per la ricerca. Ma questa eccezione viene visualizzata solo sull'emulatore o viene visualizzata anche sui dispositivi? – Nezam

+0

Scusate, aggiornerò la domanda, sto solo riscontrando il problema sul mio Nexus 7. La mia galassia nexus ed emulatore non sembrano avere il problema. Penso che sia perché sto ridimensionando le immagini. – sngreco

+1

Un riferimento debole può essere inefficace su una bitmap perché una bitmap sembra piccola per il gc. (E in generale non si dovrebbe mai 'doAnything (bmp.get())' per il motivo che il WeakReference può essere liberato.) – 18446744073709551615

risposta

4

Non sono stato in grado di determinare perché l'allocazione della memoria e la raccolta sono diverse tra le diverse piattaforme, ma sono stato in grado di mitigare il problema e impedire all'applicazione di bloccarsi su qualsiasi piattaforma ridimensionando le immagini per adattarle alla memoria disponibile.

Questa prima funzione determina dove viene archiviata la memoria Bitmap (nativa o Java), quindi calcola la memoria disponibile rimanente (in KB).

private long calcAvailableMemory() 
{ 
    long value = Runtime.getRuntime().maxMemory(); 
    String type = ""; 
    if (android.os.Build.VERSION.SDK_INT >= 11) 
    { 
     value = value/1024) - (Runtime.getRuntime().totalMemory()/1024); 
     type = "JAVA"; 
    } 
    else 
    { 
     value = value/1024) - (Debug.getNativeHeapAllocatedSize()/1024); 
     type = "NATIVE"; 
    } 
    Log.i(TAG, "calcAvailableMemory, size = " + value + ", type = " + type); 
    return value; 
} 

Questa seconda funzione crea un ImageView da allegare al layout. L'oggetto Show contiene variabili diverse Ho bisogno di inizializzare ImageView come dimensioni e percorso file ecc. Il maxImageMemory lungo è derivato dalla prima funzione, ed è quindi diviso per il numero di viste che sto allegando al layout dando la massima quantità di memoria per allocare ogni Bitmap.

private ImageView newImage(Show show, long maxImageMemory) 
{ 
    ImageView iv = new ImageView(this); 
    String filePath = comin.generateFilePath(show); 
    Bitmap bmp = scaleBitmap(filePath, maxImageMemory); 
    Log.i(TAG, "newImage, id:" + show.id + ", file:" + filePath + ", x:" + bmp.getWidth() + ", y:" + bmp.getHeight()); 
    iv.setImageBitmap(bmp); 
    iv.setScaleType(ImageView.ScaleType.FIT_XY); 
    iv.setId(show.id); 

    //set visibility 
    if (show.visible) 
     iv.setVisibility(View.VISIBLE); 
    else 
     iv.setVisibility(View.INVISIBLE); 

    //set dimensions 
    int width = (app.getWidth() * show.dimX)/100; 
    int height = (app.getHeight() * show.dimY)/100; 
    RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(width, height); 
    iv.setLayoutParams(rlp); 

    return iv; 
} 

Questa terza funzione scale bitmap che verrà caricata nel ImageView essendo creata in funzione 2. Il ciclo while è la parte importante, che è dove ho aumentare la dimensione del campione fino a quando la memoria necessaria per la bitmap è inferiore alla memoria massima disponibile.

private Bitmap scaleBitmap(String path, long maxImageMemory) 
{ 
    BitmapFactory.Options options = new BitmapFactory.Options(); 
    options.inJustDecodeBounds = true; 
    BitmapFactory.decodeFile(path, options); 

    int sample = 1; 
    //Scale image to screen resolution 
    if (options.outHeight > app.getHeight() || options.outWidth > app.getWidth()) 
    { 
     int heightRatio = Math.round((float) options.outHeight/(float) app.getHeight()); 
     int widthRatio = Math.round((float) options.outWidth/(float) app.getWidth()); 
     sample = heightRatio < widthRatio ? heightRatio : widthRatio; 
    } 

    //Scale image to stay within memory limitations 
    while (calcBitmapSize(options.outWidth, options.outHeight, sample) > maxImageMemory) 
    { 
     sample++; 
    } 

    options.inSampleSize = sample; 
    options.inPurgeable = true; 
    options.inInputShareable = true; 
    options.inJustDecodeBounds = false; 

    Log.i(TAG, "scaleBitmap, scaleSample = " + sample); 
    return BitmapFactory.decodeFile(path, options); 
} 

Questa quarta funzione calcola la quantità di memoria richiesta dal bitmap seconda della risoluzione originale, così come la dimensione del campione proposto.

private long calcBitmapSize(int width, int height, int sample) 
{ 
    long value = ((width/sample) * (height/sample) * 4)/1024; 
    Log.i(TAG, "calcBitmapSize, size = " + value); 
    return value; 
} 

Infine, ho sviluppato questa funzione per aiutare a risolvere tutti questi problemi di memoria. Registra l'utilizzo della memoria a seconda della versione di Android in esecuzione.

private void logMemory(String callingFunction) 
{ 
    long max = Runtime.getRuntime().maxMemory()/1024; 

    if (debugJavaMemory) 
    { 
     long used = Runtime.getRuntime().totalMemory()/1024; 
     long available = max - used; 
     long change = available - availableJavaMemoryOld; 
     if (availableJavaMemoryOld != 0) 
      Log.i(TAG_MEMORY, "jMEM M:" + max + ", U:" + used + ", A:" + available + ", C:" + change + ", " + callingFunction); 
     availableJavaMemoryOld = available; 
    } 
    else if (debugNativeMemory) 
    { 
     long used = Debug.getNativeHeapAllocatedSize()/1024; 
     long available = max - used; 
     long change = available - availableNativeMemoryOld; 
     if (availableNativeMemoryOld != 0) 
      Log.i(TAG_MEMORY, "nMEM M:" + max + ", U:" + used + ", A:" + available + ", C:" + change + ", " + callingFunction); 
     availableNativeMemoryOld = available; 
    } 
} 
1

Ho avuto questo problema di coppia di mesi fa, provare questo, può aiutare:

BitmapFactory.Options options = new BitmapFactory.Options(); 
options.inSampleSize = 8; 
Bitmap bitmap = BitmapFactory.decodeStream(fis, null, options); 
+0

Grazie per il tuo commento, ma al momento ho una funzione dinamica di campionamento verso il basso che ho reso disponibile per Android Training all'indirizzo http://developer.android.com/training/displaying-bitmaps/index.html. La funzione termina con la restituzione di un sampleSize valore di 1, poiché la risoluzione corrisponde all'immagine. Ogni immagine sembra utilizzare circa 8 MB di memoria (come si vede nei registri). Se una scena ha solo 4 immagini, sarebbe un totale complessivo di 32 MB, o circa la metà della memoria disponibile. – sngreco

0

Questo collegamento può aiutare a http://developer.android.com/training/displaying-bitmaps/load-bitmap.html Questo problema si pone anche quando il drawable non è disponibile nel drawable- cartella xhdpi per i grandi cellulari 720x1280. Si prega di verificare che i drawable che si stanno utilizzando siano nella cartella drawable corretta.

+0

Grazie per il tuo commento, ma ho già partecipato a quell'allenamento. L'app è progettata per caricare le immagini dalla scheda SD. Spiega il tuo ragionamento sul fatto che la cartella in cui è memorizzata l'immagine contribuirà a ridurre l'utilizzo della memoria o a rilasciare la memoria quando necessario. – sngreco

+0

Questa risposta risolverà la tua richiesta. Questo problema l'ho affrontato e risolto in questo modo e ora funziona correttamente. http://stackoverflow.com/questions/15394329/java-lang-outofmemoryerror-appears-after-sherlockactionbar-was-added/15395218#15395218 –

Problemi correlati