web-dev-qa-db-fra.com

Quand appeler le contexte d'activité OR contexte d'application?

Il y a eu beaucoup de commentaires sur ce que sont ces deux contextes .. Mais je ne comprends toujours pas très bien

Si je comprends bien, c’est une instance de sa classe, ce qui signifie que certains programmeurs vous conseillent d’utiliser this.getApplicationContext() aussi souvent que possible afin de ne "laisser fuir" aucune mémoire. C’est parce que l’autre this (obtenir le contexte de l’instance Activity) pointe vers un Activity en cours de destruction à chaque fois que l’utilisateur incline le téléphone ou quitte l’application, etc. Garbage Collector (GC) ne capture pas et utilise donc trop de mémoire ..

Mais quelqu'un peut-il, s'il vous plaît, trouver de très bons exemples de codage dans lesquels il serait judicieux d'utiliser this (obtenir le contexte de l'instance Activity actuelle) et où le contexte de l'application sera inutile/erroné?

252
Norfeldt

getApplicationContext() est presque toujours faux. Mme Hackborn (entre autres) ont été très explicites que vous seulement utilisez getApplicationContext() quand vous savez pourquoi vous utilisez getApplicationContext() et uniquement lorsque vous devez utiliser getApplicationContext().

Pour être franc, "certains programmeurs" utilisent getApplicationContext() (ou getBaseContext(), dans une moindre mesure) car leur expérience de Java est limitée. Ils implémentent une classe interne (par exemple, un OnClickListener pour un Button dans un Activity) et ont besoin d'un Context. Plutôt que d'utiliser MyActivity.this pour accéder à la classe externe 'this, ils utilisent getApplicationContext() ou getBaseContext() pour obtenir un objet Context.

Vous uniquement utilisez getApplicationContext() lorsque vous savez vous avez besoin d'un Context pour quelque chose qui peut vivre plus longtemps que tout autre probable Context que vous avez à votre disposition. Les scénarios incluent:

  • Utilisez getApplicationContext() si vous avez besoin de quelque chose lié à un Context qui aura lui-même une portée globale. J'utilise getApplicationContext(), par exemple, dans WakefulIntentService, pour le static WakeLock à utiliser pour le service. Étant donné que WakeLock est statique et que j’ai besoin d’un Context pour obtenir PowerManager, il est plus sûr d’utiliser getApplicationContext().

  • Utilisez getApplicationContext() lorsque vous vous liez à un Service à partir d'un Activity, si vous souhaitez passer le ServiceConnection (c'est-à-dire le descripteur à la liaison) entre Activity instances via onRetainNonConfigurationInstance(). Android suit en interne les liaisons via ces ServiceConnections et conserve les références à la Contexts qui crée les liaisons. Si vous liez à partir de Activity, la nouvelle instance Activity aura une référence à ServiceConnection, qui comporte une référence implicite à l'ancien Activity et à l'ancien Activity ne peut pas être ramassé.

Certains développeurs utilisent des sous-classes personnalisées de Application pour leurs propres données globales, qu’ils extraient via getApplicationContext(). C'est certainement possible. Je préfère les membres de données statiques, si pour aucune autre raison que vous ne pouvez avoir un objet personnalisé Application. J'ai construit une application à l'aide d'un objet personnalisé Application et je l'ai trouvée douloureuse. Mme Hackborn est également d’accord avec cette position .

Voici les raisons pour lesquelles pas utilisez getApplicationContext() où que vous soyez:

  • Ce n'est pas un complet Context, supportant tout ce que Activity fait. Diverses choses que vous allez essayer de faire avec cette Context vont échouer, principalement liées à l'interface graphique .

  • Cela peut créer des fuites de mémoire si la Context de getApplicationContext() conserve quelque chose créé par vos appels et que vous ne nettoyez pas. Avec un Activity, s'il garde quelque chose, une fois que le Activity a été collecté, tout le reste disparaît également. L'objet Application reste pendant toute la durée de votre processus.

390
CommonsWare

Je pense qu'il y a beaucoup de choses mal documentées sur le site du SDK, c'est l'un d'entre eux. Ce que je vais dire, c'est qu'il semble préférable d'utiliser par défaut un contexte d'application et d'utiliser uniquement un contexte d'activité lorsque vous en avez vraiment besoin. Le seul endroit où j'ai jamais vu que vous aviez besoin d'un contexte d'activité était celui d'un dialogue de progression. SBERG412 affirme que vous devez utiliser un contexte d'activité pour un message de pain grillé, mais que les documents Android indiquent clairement qu'un contexte d'application est utilisé. J'ai toujours utilisé le contexte d'application pour les toasts à cause de cet exemple de Google. Si ce n'est pas le cas, Google laisse tomber le ballon ici.

Voici plus à réfléchir et à examiner:

Pour un message de pain grillé, le guide de développement de Google utilise le contexte de l'application et indique explicitement de l'utiliser: Notifications de pain grillé

Dans la section des boîtes de dialogue du guide de développement, vous voyez qu'un AlertDialog.Builder utilise le contexte de l'application, puis la barre de progression utilise un contexte d'activité. Ce n'est pas expliqué par Google. Dialogues

Il semble qu'une bonne raison d'utiliser le contexte d'application consiste à gérer les modifications de configuration, comme une modification d'orientation, et à conserver les objets nécessitant un contexte tel que Vues. Si vous regardez ici: modifications de l'heure d'exécution Il existe une mise en garde concernant l'utilisation d'un contexte d'activité, ce qui peut créer une fuite. Cela peut être évité avec un contexte d'application avec les vues à conserver (du moins c'est ce que je comprends). Dans une application que je suis en train d'écrire, j'ai l'intention d'utiliser un contexte d'application, car j'essaie de conserver certaines vues et d'autres choses sur un changement d'orientation, et je souhaite toujours que l'activité soit détruite et recréée lors des changements d'orientation. Je dois donc utiliser un contexte d'application pour ne pas causer de fuite de mémoire (voir Eviter les fuites de mémoire ). Pour moi, il semble y avoir de nombreuses bonnes raisons d'utiliser le contexte d'application au lieu d'un contexte d'activité. Pour moi, il semble presque que vous l'utiliseriez plus souvent qu'un contexte d'activité. C'est ce que semblent faire beaucoup de Android livres, et c'est ce que font la plupart des exemples de Google que j'ai vus.

La documentation de Google donne vraiment l'impression que l'utilisation du contexte d'application convient parfaitement dans la plupart des cas, et apparaît en fait plus souvent que l'utilisation d'un contexte d'activité dans leurs exemples (du moins les exemples que j'ai vus). Si l’utilisation du contexte d’application pose un tel problème, Google doit en tenir davantage compte. Ils doivent préciser, et ils doivent refaire certains de leurs exemples. Je n’en imputerais pas la responsabilité à des développeurs inexpérimentés puisque l’autorité (Google) donne vraiment l’impression que l’utilisation de contextes d’application ne pose pas de problème.

47
Andi Jay

J'ai utilisé ce tableau pour savoir quand utiliser les différents types de contexte tels que Contexte d'application (c'est-à-dire: getApplicationContext()) et contexte d'activité , également contexte BroadcastReceiver :

enter image description here

Tous les mérites vont à l'auteur original ici pour plus d'informations.

35
CommonSenseCode

Quel contexte utiliser?

Il existe deux types de contexte:

  1. Le contexte d'application est associé à l'application et sera toujours identique pendant toute la durée de l'application - il ne change pas. Ainsi, si vous utilisez Toast, vous pouvez utiliser le contexte de l'application ou même le contexte de l'activité (les deux), car le pain grillé peut être affiché à partir de n'importe où dans votre application et n'est pas attaché à une fenêtre spécifique. Cependant, il existe de nombreuses exceptions, notamment lorsque vous devez utiliser ou transmettre le contexte d'activité.

  2. Le contexte d'activité est associé à l'activité et peut être détruit si l'activité est détruite. Il peut y avoir plusieurs activités (plus que probable) avec une seule application. Et parfois, vous avez absolument besoin du descripteur de contexte d'activité. Par exemple, si vous lancez une nouvelle activité, vous devez utiliser le contexte de l'activité dans son intention afin que la nouvelle activité de lancement soit connectée à l'activité en cours en termes de pile d'activités. Cependant, vous pouvez également utiliser le contexte de l'application pour lancer une nouvelle activité, mais vous devez ensuite définir l'indicateur Intent.FLAG_ACTIVITY_NEW_TASK dans l'intention de la traiter comme une nouvelle tâche.

Considérons quelques cas:

  • MainActivity.this fait référence au contexte MainActivity qui étend la classe d'activité, mais la classe de base (activité) étend également la classe de contexte, de sorte qu'elle peut être utilisée pour offrir un contexte d'activité.

  • getBaseContext() offre un contexte d'activité.

  • getApplication() offre le contexte d'application.

  • getApplicationContext() offre également un contexte d'application.

Pour plus d'informations s'il vous plaît vérifier ceci lien .

11
Zohra Khan

Je me demandais pourquoi ne pas utiliser le contexte d'application pour chaque opération prise en charge. En fin de compte, cela réduit les risques de fuite de mémoire et de vérification des valeurs manquantes pour getContext () ou getActivity () (lors de l'utilisation d'un contexte d'application injecté ou acquis via une méthode statique à partir d'Application). Des instructions, comme celle de Ms. Hackborn n'utilise le contexte d'application que si nécessaire, ne me semble pas convaincant sans une explication. Mais il semble que j'ai trouvé un non-porté pourquoi:

ont constaté des problèmes sur certaines combinaisons de version/périphérique Android qui ne respectent pas ces règles. Par exemple, si un contexte est transmis à BroadcastReceiver et que je convertis ce contexte en un contexte d'application, puis que j'essaie d'appeler registerReceiver () sur le contexte d'application, il existe de nombreuses instances dans lesquelles cela fonctionne correctement, mais également dans lesquelles je reçois un crash à cause d'une ReceiverCallNotAllowedException. Ces accidents se produisent sur un large éventail de Android versions allant des API 15 à 22. https://possiblemobile.com/2013/06/context/#comment-2443283153

Parce qu'il n'est pas garanti que toutes les opérations décrites comme étant prises en charge par Application Context dans le tableau ci-dessous fonctionneront sur tous les appareils Android! enter image description here

4
Malachiasz

Deux exemples intéressants d'utilisation du contexte d'activité par rapport au contexte d'application sont l'affichage d'un message Toast ou d'un message de dialogue intégré, car l'utilisation du contexte d'application provoquera une exception:

ProgressDialog.show(this, ....);

ou

Toast t = Toast.makeText(this,....);

Ces deux éléments ont besoin d'informations provenant du contexte d'activité qui ne sont pas fournies dans le contexte d'application.

3
SBerg413

Contexte d'application en direct jusqu'à ce que votre application soit active uniquement et ne dépend pas sur le cycle de vie de l'activité mais, le contexte garde l'objet à long terme . Si l’objet que vous utilisez est temporaire, l’utilisation de contexte de l’application et contexte de l’activité est totalement différente de celle du contexte de l’application.

3
Ganesh Katikar