Avertissement: Ne placez pas de classes de contexte Android dans des champs statiques; il s’agit d’une fuite de mémoire (et interrompt également l’exécution instantanée)

Studio Android:

Ne placez pas les classes de contexte Android dans des champs statiques; il s’agit d’une fuite de mémoire (et interrompt également l’exécution instantanée)

Donc 2 questions:

# 1 Comment appelez-vous un startService partir d’une méthode statique sans variable statique pour le contexte?
# 2 Comment envoyez-vous une diffusion locale à partir d’une méthode statique (même)?

Exemples:

 public static void log(int iLogLevel, Ssortingng sRequest, Ssortingng sData) { if(iLogLevel > 0) { Intent intent = new Intent(mContext, LogService.class); intent.putExtra("UPDATE_MAIN_ACTIVITY_VIEW", "UPDATE_MAIN_ACTIVITY_VIEW"); mContext.startService(intent); } } 

ou

  Intent intent = new Intent(MAIN_ACTIVITY_RECEIVER_INTENT); intent.putExtra(MAIN_ACTIVITY_REQUEST_FOR_UPDATE, sRequest)); intent.putExtra(MAIN_ACTIVITY_DATA_FOR_VIEW, sData); intent.putExtra(MAIN_ACTIVITY_LOG_LEVEL, iLogLevel); LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent); 

Quelle serait la manière correcte de le faire sans utiliser mContext ?

NOTE: Je pense que ma principale question pourrait être de savoir comment transmettre un contexte à une classe à partir de laquelle la méthode appelante réside.

Il suffit de le transmettre en paramètre à votre méthode. Il n’y a aucun sens à créer une instance statique de Context uniquement dans le but de démarrer une Intent .

Voici comment votre méthode doit ressembler:

 public static void log(int iLogLevel, Ssortingng sRequest, Ssortingng sData, Context ctx) { if(iLogLevel > 0) { Intent intent = new Intent(ctx, LogService.class); intent1.putExtra("UPDATE_MAIN_ACTIVITY_VIEW", "UPDATE_MAIN_ACTIVITY_VIEW"); ctx.startService(intent); } } 

Mise à jour à partir des commentaires sur la question: cascade le contexte de l’activité initiasortingce (via les parameters du constructeur ou les parameters de la méthode) jusqu’au point où vous en avez besoin.

Assurez-vous simplement de passer context.getApplicationContext () ou d’appeler getApplicationContext () sur tout contexte transmis via des méthodes / constructeur à votre singleton si vous décidez de le stocker dans un champ membre.

exemple de preuve idiot (même si quelqu’un passait dans une activité, il accaparerait le contexte de l’application et l’utiliserait pour instancier le singleton):

 public static synchronized RestClient getInstance(Context context) { if (mInstance == null) { mInstance = new RestClient(context.getApplicationContext()); } return mInstance; } 

getApplicationContext () selon les documents: “Retourne le contexte de l’object Application unique et global du processus en cours.”

Cela signifie que le contexte renvoyé par “getApplicationContext ()” passera par tout le processus et que cela n’a pas d’importance si vous stockez une référence statique n’importe où car il sera toujours présent pendant l’exécution de votre application (et survit aux objects / singletons instancié par elle).

Comparez cela au contexte à l’intérieur des vues / activités contenant de grandes quantités de données, si vous perdez un contexte détenu par une activité, le système ne pourra pas libérer cette ressource, ce qui n’est évidemment pas bon.

Une référence à une activité par son contexte devrait vivre le même cycle de vie que l’activité elle-même, sinon le contexte restrait en otage et provoquerait une fuite de mémoire (qui est la raison de l’avertissement de peluches).

EDIT: Pour le gars qui cite l’exemple de la documentation ci-dessus, il y a même une section de commentaire dans le code sur ce que je viens d’écrire à propos de:

  // getApplicationContext() is key, it keeps you from leaking the // Activity or BroadcastReceiver if someone passes one in. 

C’est juste un avertissement. Ne t’inquiète pas. Si vous souhaitez utiliser un contexte d’application, vous pouvez l’enregistrer dans une classe “singleton”, utilisée pour enregistrer toute la classe singleton dans votre projet.

Dans votre cas, cela n’a pas beaucoup de sens de l’avoir comme champ statique, mais je ne pense pas que ce soit mauvais dans tous les cas. Si vous faites maintenant ce que vous faites, vous pouvez avoir un champ statique qui a un contexte et le rendre plus tard. Je crée une instance statique pour ma classe de modèle principale qui a un contexte à l’intérieur, son contexte d’application et son contexte d’activité. Je ne vois pas que j’ai une fuite de mémoire. Donc, si un gars intelligent pense que je me trompe, n’hésitez pas à commenter …

Aussi Instant Run fonctionne bien ici …

En général, évitez d’avoir des champs de contexte définis comme statiques. L’avertissement lui-même explique pourquoi: c’est une fuite de mémoire. Briser la course instantanée n’est peut-être pas le plus gros problème de la planète.

Maintenant, il y a deux scénarios où vous obtenez cet avertissement. Pour une instance (la plus évidente):

 public static Context ctx; 

Et puis il y a le plus compliqué, où le contexte est enveloppé dans une classe:

 public class Example{ public Context ctx; //Constructor omitted for brievety } 

Et cette classe est définie comme statique quelque part:

 public static Example example; 

Et vous aurez l’avertissement.

La solution elle-même est assez simple: ne placez pas de champs de contexte dans des instances statiques , que ce soit une classe d’encapsulation ou une déclaration statique directe.

Et la solution à cet avertissement est simple: ne placez pas le champ de manière statique. Dans votre cas, transmettez le contexte en tant qu’instance à la méthode. Pour les classes où plusieurs appels de contexte sont effectués, utilisez un constructeur pour transmettre le contexte (ou une activité à cet égard) à la classe.

Notez que c’est un avertissement, pas une erreur. Si, pour une raison quelconque, vous avez besoin d’ un contexte statique, vous pouvez le faire. Bien que vous créez une fuite de mémoire lorsque vous le faites.