English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Brève analyse des méthodes de prévention des dépassements de mémoire en programmation Android

Ce document illustre les exemples de débordement de mémoire en programmation Android et les méthodes de prévention. Partageons-les avec tous pour consultation, voici les détails :

 Le moteur virtuel d'Android est basé sur le registre Dalvik, sa taille maximale de pile est généralement16M. Cependant, Android est écrit en Java, donc dans une large mesure, le mécanisme de mémoire d'Android est équivalent au mécanisme de mémoire de Java. Au début du développement, les problèmes de limitation de la mémoire peuvent nous apporter des problèmes graves tels que les débordements de mémoire. Lorsque nous ne utilisons pas de mémoire, nous devons éviter de conserver l'état nécessaire sur d'autres plateformes ou d'autres programmes en cours d'exécution, afin que les processus morts apportent des problèmes de mémoire. Cela devrait être libéré le plus possible lors de la fermeture du programme ou de la sauvegarde de l'état, ce qui peut améliorer la fluidité du système en cours d'exécution.

La mémoire principale d'Android se manifeste :

1Sur la plateforme Android, conserver longtemps des références à des ressources peut entraîner que certaines mémoires ne puissent pas être libérées, ce qui provoque de nombreux problèmes de fuites de mémoire. Par exemple : Contexte (les Activity mentionnées ci-dessous sont des Contexte), lorsque vous devez conserver l'état de votre première classe d'objet et le transmettre à d'autres objets de classe, vous devez d'abord libérer l'objet de réception avant de supprimer la première classe d'objet. Il faut noter un point : dans le mécanisme de mémoire de Java ou d'Android, avant de libérer le nœud de sommet, il faut s'assurer que d'autres objets ne l'appellent pas, afin que le système GC puisse le libérer et le recyclage. Regardons un morceau de code :

@Override
protected void onCreate(Bundle state) {
   super.onCreate(state);
   TextView label = new TextView(this);
   label.setText("Leaks are bad");
   setContentView(label);
{}

Le code signifie que nous avons chargé une instance de TextView dans l'Activity (Contexte) en cours d'exécution. Par conséquent, grâce au mécanisme de recyclage de la GC, nous savons que pour libérer le Contexte, il faut d'abord libérer les objets qui lui sont associés. Sinon, lors de la libération du Contexte, vous découvrirez que de grandes quantités de mémoire sont en excès. Donc, par inadvertance, les débordements de mémoire sont très faciles à rencontrer. Lorsque vous sauvegardez des objets, cela peut également entraîner des fuites de mémoire. Le plus simple est, par exemple, un Bitmap, par exemple : lors de la rotation de l'écran, cela endommagera l'état de l'Activity en cours de conservation et créera une nouvelle Activity, jusqu'à ce que l'état de la nouvelle Activity soit sauvegardé. Regardons un autre morceau de code :

private static Drawable sBackground;
@Override
protected void onCreate(Bundle state) {
super.onCreate(state);
TextView label = new TextView(this);
label.setText("Les fuites de mémoire sont mauvaises");
if (sBackground == null) {
   sBackground = getDrawable(R.drawable.large_bitmap);
{}
label.setBackgroundDrawable(sBackground);
setContentView(label);
{}

Ce code est à la fois très rapide et incorrect. Les fuites de mémoire sont faciles à apparaître lors du changement de direction de l'écran. Bien que nous ne voyions pas explicitement sauvegarder l'instance Context, lorsque nous connectons l'image dessinée à une vue, le Drawable indique que le View est configuré pour les rappels, ce qui signifie que dans le code ci-dessus, nous avons déjà référencé cette Activity lors de la dessin de TextView dans l'activité. Les liens peuvent se manifester sous forme de : Drawable->TextView->Context.

Donc, lorsque vous souhaitez libérer le Context, il reste en mémoire, il n'est pas libéré.

Comment éviter cette situationIl s'agit principalement de. Les threads sont les plus sujets aux erreurs. Ne négligez pas les threads, dans Android, les threads sont les plus susceptibles de causer des fuites de mémoire. La principale raison pour laquelle les threads causent des fuites de mémoire est l'irrégularité de leur cycle de vie. Voici un exemple de code :

public class MyTest extends Activity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    new MyThread().start();
  {}
  private class MyThread extends Thread{
    @Override
    public void run() {
      super.run();
      //do somthing
    {}
  {}
{}

Le code est simple, mais sur Android, nous avons de nouveaux problèmes, lorsque nous changeons d'écran de vue (portrait ou paysage), nous devons reconstruire l'Activity en mode portrait ou paysage. Nous pensons intuitivement que l'Activity précédemment créée sera recyclée, mais comment cela se passe-t-il vraiment ? Le mécanisme Java ne vous donnera pas le même sentiment, car avant que la fonction run ne se termine, MyThread n'est pas détruit, donc l'Activity (Mytest) qui le référence n'est pas non plus détruite, ce qui entraîne également des fuites de mémoire.

Certains préfèrent utiliser AsyncTaskfourni par Android, mais en réalité, les problèmes d'AsyncTasksont plus graves. Le problème de fuite de mémoire ne se produit que lorsque la fonction runnede Threadn'est pas terminée, mais le mécanisme interne d'AsyncTaskutilise ThreadPoolExecutor, et la durée de vie des objets Threadgénérés par cette classe n'est pas déterminée, ce qui n'est pas contrôlé par l'application. Par conséquent, si AsyncTaskest utilisé comme classe interne d'Activity, il est plus facile de se produire des problèmes de fuite de mémoire.

Les principales méthodes d'amélioration des problèmes de thread consistent en :

① Changez la classe interne de thread en classe interne statique.
② Privilégiez l'utilisation de références faibles pour conserver Contextdans le programme.

2... Bitmap laid...

Bitmap est un objet très laid, pour un objet mémoire, si l'objet occupe une grande mémoire, et lorsque l'objet dépasse la limite de mémoire du système, le problème de fuite de mémoire est évident.....
La résolution des problèmes de bitmap consiste principalement à éviter de conserver l'image en mémoire ou à réduire le taux de résolution. Dans de nombreux cas, en raison de la haute résolution des pixels de nos images, et pour la taille de l'écran du téléphone, nous n'avons pas besoin d'une image de haute résolution pour charger, nous pouvons d'abord réduire le taux de résolution de l'image pour les opérations UI originales.

Si nous ne devons pas conserver de référencesàl'objet bitmaplorsque nous n'en avons pas besoin, nous pouvons également utiliser des références faibles comme remplacement. De nombreux exemples de codes spécifiques peuvent être trouvés sur Google.

En résumé, pour éviter les fuites de mémoire, il est principalement nécessaire de suivre les points suivants :

Première : Ne conservez pas longtemps des référencesàContext (si vous devez utiliser Context, assurez-vous que l'objet de référence et son cycle de vie sont cohérents).

Deuxième : Si vous devez utiliser Context, préférez ApplicationContextàContext, car la durée de vie d'ApplicationContextest plus longue et ne cause pas de fuites de mémoire en cas de référence.

Troisième : Évitez d'utiliser des variables statiques dans vos Activitylorsque vous ne contrôlez pas la durée de vie des objets. Privilégiez l'utilisation de WeakReferenceà la place d'une variable statique.

Quatrième : Le回收器ne garantit pas que le回收内存soit précis, donc, lors de l'utilisation des contenus nécessaires, il est principalement nécessaire de gérer la durée de vie et de libérer les objets inutiles en temps opportun. Essayez de libérer les autres objets que nous avons référencés dans onDestroyà la fin de la vie de l'Activity, par exemple : cursor.close().

En réalité, nous pouvons utiliser moins de code dans de nombreux aspects pour terminer le programme. Par exemple : nous pouvons utiliser davantage9patch images, etc. Il y a beaucoup de détails où nous pouvons découvrir et explorer plus de problèmes de mémoire./C++Pour le principe de "celui qui crée, celui qui libère" du programme, notre maîtrise de la mémoire n'est pas inférieure à celle de Java ou du mécanisme GC de l'Android lui-même, et une meilleure maîtrise de la mémoire peut rendre notre téléphone plus fluide.

Les lecteurs intéressés par plus de contenu sur Android peuvent consulter les sujets spéciaux de ce site : "Résumé des techniques de mémoire et de cache pour le développement Android", "Tutoriel d'entrée et de niveau supérieur pour le développement Android", "Résumé des techniques de débogage et des solutions de problèmes courants pour le développement Android", "Résumé des techniques d'opération multimédia pour Android (audio, vidéo, enregistrement, etc.), "Résumé des utilisations des composants de base d'Android", "Résumé des techniques de View d'Android", "Résumé des techniques de layout d'Android" et "Résumé des utilisations des contrôles d'Android"

J'espère que l'article décrit ici peut aider les développeurs Android.

Déclaration : le contenu de cet article est issu du réseau, la propriété intellectuelle appartient à ses auteurs respectifs, le contenu est apporté par les utilisateurs d'Internet de manière spontanée et auto-proposée, ce site Web ne détient pas de propriété intellectuelle, n'a pas été édité par l'homme, et n'assume pas de responsabilité juridique en ce qui concerne les responsabilités juridiques. Si vous trouvez du contenu suspect de violation de droits d'auteur, veuillez envoyer un e-mail à : notice#w3En fait, nous pouvons utiliser moins de code dans de nombreux aspects pour terminer le programme. Par exemple : nous pouvons utiliser davantage

Vous pourriez aussi aimer