8

Ho un sistema di battaglia complesso che ha 1 attività padre e diverse classi figlio che accedono alle variabili statiche di BattleActivity estendendo Battle e passando il contesto a quelle classi.Android - rilascio memoria allocata AnimationDrawable sta usando

Tutto sembra funzionare correttamente, tuttavia sto avendo un problema con il rilascio di tutti i miei AnimationDrawables dalla memoria. Ci possono essere un totale di 24 DrawableAnimations usate durante una battaglia. Per ora è tutto ok, tuttavia ogni volta che l'utente incontra un nuovo mostro vengono aggiunti alla memoria altri 4 AnimationDrawables che lentamente ma sicuramente causeranno l'arresto anomalo della mia App con l'eccezione di memoria esaurita.

Pertanto, ho davvero bisogno di trovare un modo per liberare tutta la memoria che il mio sistema di battaglia occupa non appena esco. Attualmente sto provando su una Sony Z2 e quando l'utente entra in una battaglia il mmeory aumenta da 91mb a 230mb. Ho bisogno di riportare questo utilizzo della memoria a 91mb quando la battaglia si è conclusa. Ho aggiunto alcuni snippet di codice molto semplici per darti un'idea di come l'app scorre attualmente e di cosa sto cercando di fare per rilasciare la memoria.

public class Battle extends Activity 
{ 
    // I have several AnimationDrawables loaded into memory 
    // These are then assigned the relevent animation to a button swicthing between these animations throughout my battle 
    ImageButton btnChr1; 
    AnimationDrawable cAnimHit1; 
} 

//This is the use of one of those AnimationDrawables 
public class Battle_Chr_Anim extends Battle 
{ 
    protected Context ctx; 
    private ImageButton btnChr1; 
    AnimationDrawable cAnimHit1; 

    public Battle_Chr_Anim(Context c, ImageButton _btnChr1, AnimationDrawable _cAnimHit1) { 
     this.ctx = c; 
     this.btnChr1 = _btnChr1; 
     this.cAnimHit1 = _cAnimHit1; 
    } 

    // Bound the ImageButton 
    int id = ctx.getResources().getIdentifier("idle", "drawable", ctx.getPackageName()); 
    img_chr1.setBackgroundResource(id); 
    frameAnimation = (AnimationDrawable)img_chr1.getBackground(); 
    frameAnimation.start() 

    // Loaded into memory ready so I can swicth them over quickly when user attacks 
    int ca1 = ctx.getResources().getIdentifier("attack", "drawable", ctx.getPackageName()); 
    cAnimHit1 = (AnimationDrawable)chrHit1.getBackground(); 
    cAnimHit1.start(); 
} 

public class Battle_Ended extends Battle 
{ 
    protected Context ctx; 

    public Battle_Ended(Context c) { 
     this.ctx = c; 
    } 

    //This is a dialog popup when the user completes the battle closing the battle activty 
    void EndBattle() 
    { 
     ImageButton btnSubmit = (ImageButton)dialog.findViewById(R.id.imgBtnSubmit); 
     btnSubmit.setOnClickListener(new OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       Intent returnIntent = new Intent(); 
       setResult(RESULT_CANCELED, returnIntent); 
       RecyleAllAnimations(); 
       dialog.dismiss(); 
       ((Activity) ctx).finish(); 
      } 
     }); 
    } 

    void RecyleAllAnimations() 
    { 
     // I want all AnimationDrawables from memory here, I believe the below line removes the one currently in use, however I have no way of releasing the other animations sitting in memory. 
     img_chr1.setBackgroundResource(android.R.color.transparent); 
     System.gc(); 
    } 
} 
+0

Avete davvero variabili statiche che passate nel contesto dell'applicazione? penso che uccideranno la tua app molto prima dei tuoi drawable – TheRedFox

+0

Sì, questo è solo per la mia parte di battaglia, perché non volevo tutto il mio codice nella stessa attività e semplicemente estendevo questa classe in modo che potessi ancora accedere alla UI.Poiché devo essere in grado di caricare tutti gli AnimationDrawable prima di caricare l'attività in modo che le animazioni possano essere fluide quando l'utente entra in una battaglia –

risposta

0

prima di tutto penso che non si può fare qualsiasi riciclaggio per AnimationDrawable a meno che non si lascia il campo di applicazione, che sono dichiarate. non inoltrare su System.gc(); e lasciare che GC rilasci automaticamente la memoria per te.

cui accedere alle variabili statiche del BattleActivity

È questo il tuo primo errore. Se usi la variabile statica anche se lasci la tua attività sono tutti lì e otterrai sicuramente OOM.

Pertanto, ho davvero bisogno di trovare un modo per liberare tutta la memoria che il mio sistema di battaglia occupa non appena esco.

se si dichiarano tutte le variabili come variabili non statiche, non si ottiene OOM quando si lascia l'ambito definito. anche se è possibile ottenere OIM se si crea AnimationDrawable senza limiti durante l'attività è in esecuzione.

+0

Ho modificato il mio codice in modo da non utilizzare più AnimationDrawable statico, tuttavia sono ancora fermo avendo un problema nel rilasciare la memoria anche dopo che l'attività è stata distrutta e l'utente è tornato alla pagina Mappa di gioco. Altre idee? –

+0

quale problema hai ora? – mmlooloo

+0

Beh, semplicemente, la memoria non viene rilasciata per AnimatonDrawables –

0

L'utilizzo di Drawable (s) statici o View (s) causerà una perdita di memoria perché i drawable sono stateful.

Si potrebbe o verificare la presenza di qualsiasi altro Drawable statico (s) o View (s) e di sbarazzarsi di loro o chiamare

drawable.setCallback(null); 

Non è possibile riciclare oggetti Drawable e non è una buona pratica di chiamata di sistema .gc()

Sembra che la tua app soffra di una perdita di memoria da qualche parte, se hai provato quanto sopra e la memoria si espande ancora a quel ritmo, allora considera di fare memory analysis per restringere il problema.

+0

Non penso che sia il fatto che soffro di perdita di memoria, penso che sia la quantità di memoria a taglio utilizzabile. Voglio dire che su un carico ho 30 AnimationDrawable che devono essere caricati, ciascuno composto da circa 15 immagini ciascuna 256 px x 256 px. Quindi, come previsto, l'utilizzo della memoria aumenta (ci vogliono anche 2-4 secondi per caricare in base al dispositivo). Questo posso affrontarlo, tuttavia, a parte questo, ho bisogno di rilasciare quella memoria in qualche modo. Ogni volta che si incontra un nuovo mostro vengono aggiunti altri 5 AnimationDrawables alla memoria –

+0

Questo è vero ma se la tua attività non è trapelata, la memoria dovrebbe essere rilasciata come necessario, anche se hai chiamato System.gc() manualmente dopo aver chiuso l'attività quelli Drawable (s) dovrebbe essere cancellato dalla memoria a meno che non ci sia una perdita. Cosa succede se si assicura che nessun Drawable statico sia usato e le altre cose che ho menzionato fanno puntare a null al termine per evitare possibili Loitering –

+0

Penso che dovrò esaminare questo stasera come necessità di rimuovere lo static da tutte le ImageViews e ImageButtons possono quindi testarlo correttamente. Qual è il modo di vestire per controllare una perdita di memoria e uno strumento di analisi della memoria? –