2011-09-07 10 views
2

Je rencontre des problèmes pour trouver une fuite de mémoire dans mon application Mono pour Android. Je crois que je suis toutes les meilleures pratiques, décrites plus tard, mais je continue à obtenir OutOfMemoryError après un nombre cohérent et reproductible de run-throughs d'une activité. En utilisant ddms sur l'émulateur, je peux voir que mon application consomme environ 200 "objets de données" supplémentaires et environ 30 Ko de mémoire chaque fois que notre ViewFlipper retourne à la page suivante. Nous consommons également d'autres ressources, mais à un taux beaucoup plus bas. J'utilise le ViewFlipper un peu peu conventionnel; il retourne dans une seule direction, et retirez le View s qui ont déjà été montré:Mono pour Android - OutOfMemoryError

while (flipper.ChildCount > 2) 
{ 
    flipper.RemoveViewAt(0); 
} 

J'ai pris grand soin de Dispose() de toute référence à toutes les View s que nous avons utilisé, comme described in this blog post. J'utilise using religieusement pour tous les composants de l'interface utilisateur (qui Dispose() automatiquement l'objet à la fin du champ d'application):

using (TextView questionView = header.FindViewById<TextView>(Resource.Id.question)) 
{ 
    questionView.Text = question.Text; 
} 

Cela ne semble pas avoir d'effet sur la fuite de mémoire. J'utilise le même modèle chaque fois que je charge Bitmap s (généralement des fichiers PNG de moins de 20 Ko), ce que je fais assez souvent.

Mise à jour: je charge bitmaps en utilisant une méthode d'extension:

public static Bitmap BitmapFromAsset(this Context context, String asset) 
{ 
    Bitmap bitmap; 
    using (Stream stream = context.Assets.Open(asset)) 
    { 
     bitmap = BitmapFactory.DecodeStream(stream); 
     stream.Close(); 
    } 
    return bitmap; 
} 

Les bitmaps sont ensuite utilisés comme ceci:

using (Bitmap b = this.BitmapFromAsset(path)) 
{ 
    imageView.SetImageBitmap(b); 
} 

Mise à jour: Comme Aranda suggère ci-dessous, j'utiliser des délégués , donc c'est un modèle commun dans mon code:

using (View button = FindViewById(Resource.Id.button)) 
{ 
    button.Click += delegate 
    { 
     // do something 
    }; 
} 

Modification de ce que je supprime les gestionnaires lorsque le View est supprimé ne fait aucune différence dans la fuite.

Mise à jour: Bug posted with Xamarin with example project.

Répondre

1

J'ai eu un problème légèrement similaire, et très difficile à trouver (albiet sur WP7, mais c'est toujours pertinent car tout est .Net). Il s'est avéré que j'avais attaché des délégués à mon cours GameScreen d'un autre cours qui n'était pas hors de portée. Assurez-vous que vous faites - = tous les événements joints et délégués ainsi que la perte de la référence à l'instance de vue.

+0

Oui, j'utilise delegate pour attacher aux différents 'View's. Donc, je dois supprimer tous les gestionnaires d'événements qui utilisent des délégués, ou tous les gestionnaires d'événements en général? Supposons que vous ayez ceci: 'en utilisant (Bouton b = FindViewById

+0

Même en supprimant les gestionnaires Click de l'équation, j'ai toujours des fuites de mémoire comme décrit ci-dessus. –

+0

Intéressant. Votre exemple particulier ne provoquerait pas de fuite car le délégué est une méthode anonyme et serait dans la portée de l'instance de vue elle-même. Je pense que je ne me suis pas bien expliqué non plus. La mienne coulait parce que mon GameScreen avait attaché une de ses méthodes à un événement (ou un délégué) dans ma classe Engine. Le moteur tenait toujours une référence à la classe GameScreen via l'événement joint.Pas forcément quoi que ce soit à voir avec votre fuite :( – Aranda