Il y a eu beaucoup de publications sur ce que sont ces deux contextes. Mais je n’ai toujours pas raison
Si je comprends bien, chacun d’eux est une instance de sa classe, ce qui signifie que certains programmeurs vous recommandent d’utiliser this.getApplicationContext()
aussi souvent que possible afin de ne pas “fuir” la mémoire. C’est parce que l’autre this
(obtenir le contexte de l’instance d’ Activity
) pointe vers une Activity
qui est détruite à chaque fois que l’utilisateur bascule le téléphone ou quitte l’application, etc. trop de mémoire ..
Mais quelqu’un peut-il s’il vous plaît trouver des exemples de codage vraiment bons où ce serait la bonne chose à utiliser (obtenir le contexte de l’instance d’ Activity
cours) et le contexte de l’application sera inutile / faux?
getApplicationContext()
presque toujours tort. Mme Hackborn (parmi d’autres) a été très explicite: vous utilisez uniquement getApplicationContext()
lorsque 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 Java est limitée. Ils implémentent une classe interne (par exemple, un OnClickListener
pour un Button
dans une 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 object Context
.
Vous utilisez uniquement getApplicationContext()
lorsque vous savez que vous avez besoin d’un Context
pour quelque chose qui pourrait vivre plus longtemps que tout autre Context
probable dont vous disposez. Les scénarios comprennent:
Utilisez getApplicationContext()
si vous avez besoin de quelque chose lié à un Context
qui aura lui-même une scope globale. J’utilise getApplicationContext()
, par exemple, dans WakefulIntentService
, pour que le WakeLock
statique soit utilisé pour le service. Étant donné que WakeLock
est statique et que j’ai besoin d’un Context
pour que PowerManager
le crée, il est plus sûr d’utiliser getApplicationContext()
.
Utilisez getApplicationContext()
lorsque vous vous getApplicationContext()
à un Service
partir d’une Activity
, si vous souhaitez transmettre ServiceConnection
(c’est-à-dire le handle à la liaison) entre les instances d’ Activity
via onRetainNonConfigurationInstance()
. Android suit en interne les liaisons via ces ServiceConnections
et contient des références aux Contexts
qui créent les liaisons. Si vous vous liez à partir de l’ Activity
, la nouvelle instance d’ Activity
aura une référence à ServiceConnection
qui a une référence implicite à l’ancienne Activity
et l’ancienne Activity
ne peut pas être collectée.
Certains développeurs utilisent des sous-classes personnalisées d’ Application
pour leurs propres données globales, qu’ils récupèrent via getApplicationContext()
. C’est certainement possible. Je préfère les membres de données statiques si, pour une autre raison, vous ne pouvez avoir qu’un seul object Application
personnalisé. J’ai construit une application en utilisant un object Application
personnalisé et j’ai trouvé que c’était douloureux. Mme Hackborn est également d’accord avec cette position .
Voici les raisons pour lesquelles vous ne getApplicationContext()
pas utiliser getApplicationContext()
où que vous alliez:
Ce n’est pas un Context
complet, supportant tout ce que fait l’ Activity
. Diverses choses que vous essayerez de faire avec ce Context
échoueront, principalement en ce qui concerne l’interface graphique .
Il peut créer des memory leaks, si le Context
de getApplicationContext()
contient quelque chose créé par vos appels que vous ne nettoyez pas. Avec une Activity
, si elle retient quelque chose, une fois que l’ Activity
reçoit des ordures, tout le rest disparaît. L’object Application
rest pour toute la durée de votre processus.
Je pense qu’il y a beaucoup de choses mal documentées sur le site du SDK, c’est l’une d’entre elles. L’affirmation que je vais faire est qu’il semble préférable d’utiliser un contexte d’application par défaut et de n’utiliser un contexte d’activité que lorsque cela est vraiment nécessaire. Le seul endroit où j’ai jamais vu que vous avez besoin d’un contexte d’activité est celui d’une boîte de dialog de progression. SBERG412 affirme que vous devez utiliser un contexte d’activité pour un message de toast, mais les documents Android montrent clairement qu’un contexte d’application est utilisé. J’ai toujours utilisé le contexte d’application pour les toasts à cause de cet exemple Google. Si ce n’est pas le cas, alors Google a laissé tomber la balle ici.
Voici plus à réfléchir et à revoir:
Pour un message de pain grillé, le Guide de développement Google utilise le contexte de l’application et indique explicitement son utilisation: Notifications Toast
Dans la section des boîtes de dialog du guide de développement, vous voyez qu’un AlertDialog.Builder utilise le contexte de l’application, puis que 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 un contexte d’application est lorsque vous souhaitez gérer des modifications de configuration comme un changement d’orientation et que vous souhaitez conserver des objects nécessitant un contexte tel que Views. Si vous regardez ici: Modifications du temps d’exécution Il existe un avertissement concernant l’utilisation d’un contexte d’activité, 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 j’écris, j’ai l’intention d’utiliser un contexte d’application car j’essaie de conserver certaines vues et d’autres choses lors d’un changement d’orientation, et je souhaite quand même 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 provoquer de fuite de mémoire (voir Éviter les memory leaks ). Pour moi, il semble y avoir beaucoup de bonnes raisons d’utiliser le contexte applicatif au lieu d’un contexte d’activité, et pour moi, il semble presque que vous l’utilisiez plus souvent qu’un contexte d’activité. C’est ce que beaucoup de livres Android que j’ai vus semblent faire, et c’est ce que beaucoup des exemples de Google que j’ai vus font.
La documentation de Google donne vraiment l’impression que l’utilisation d’un contexte d’application est parfaite dans la plupart des cas, et apparaît en fait plus souvent que l’utilisation d’un contexte d’activité dans leurs exemples (au moins les exemples que j’ai vus). Si c’est vraiment un problème d’utiliser le contexte d’application, alors Google doit vraiment mettre davantage l’accent là-dessus. Ils doivent le faire savoir et ils doivent refaire certains de leurs exemples. Je ne blâme pas entièrement les développeurs inexpérimentés, car l’autorité (Google) donne vraiment l’impression que l’utilisation de contextes d’application ne pose aucun problème.
J’ai utilisé ce tableau comme guide pour savoir quand utiliser les différents types de contexte tels que le contexte d’application (par exemple: getApplicationContext()
) et le contexte d’activité , ainsi que le contexte BroadcastReceiver :
Article original ici pour plus d’informations.
Quel contexte utiliser?
Il existe deux types de contexte:
Le contexte d’application est associé à l’application et sera toujours le même tout au long de la vie de l’application – il ne change pas. Donc, si vous utilisez Toast, vous pouvez utiliser le contexte d’application ou même le contexte d’activité (les deux), car le toast peut être affiché de n’importe où dans votre application et n’est pas associé à une fenêtre spécifique. Mais il existe de nombreuses exceptions, à une exception près lorsque vous devez utiliser ou transmettre le contexte d’activité.
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 d’activité dans son intention pour que la nouvelle activité de lancement soit connectée à l’activité en cours en termes de stack 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 le traiter comme une nouvelle tâche.
Considérons quelques cas:
MainActivity.this
fait référence au contexte MainActivity qui étend la classe Activity mais la classe de base (activity) étend également la classe Context, ce qui permet de proposer un contexte d’activité.
getBaseContext()
offre un contexte d’activité.
getApplication()
offre un contexte d’application.
getApplicationContext()
offre également un contexte d’application.
Pour plus d’informations, veuillez consulter ce lien .
Lorsque vous affichez un message Toast ou un message Dialog intégré, vous pouvez utiliser deux exemples de contexte:
ProgressDialog.show(this, ....);
ou
Toast t = Toast.makeText(this,....);
Ces deux éléments nécessitent des informations provenant du contexte d’activité qui ne sont pas fournies dans le contexte d’application.
Le contexte d’application en direct jusqu’à ce que votre application ne soit vivante que et qu’elle ne dépend pas du cycle de vie d’activité, mais que le contexte garde l’object de longue durée . Si l’object que vous utilisez est temporaire, ce temps utilise le contexte d’application et le contexte d’activité est utilisé totalement du contexte d’application.
Je me demandais pourquoi ne pas utiliser le contexte d’application pour chaque opération qu’il prend en charge. En fin de compte, cela réduit les risques de fuite de mémoire et de vérification de null manquante pour getContext () ou getActivity () (lors de l’utilisation du contexte d’application injecté ou acquis via une méthode statique à partir d’Application). Les déclarations, comme celle de Mme Hackborn pour utiliser le contexte d’application seulement si nécessaire, ne me semblent pas convaincantes sans une explication. Mais il semble que j’ai trouvé un vêtement pour pourquoi:
ont constaté qu’il existe des problèmes sur certaines combinaisons de versions / périphériques Android qui ne respectent pas ces règles. Par exemple, si un contexte est transmis à un BroadcastReceiver et que je convertis ce contexte en un contexte d’application, puis que j’essaie d’appeler registerReceiver () sur le contexte d’application, cela se produit dans de nombreux cas, mais un plantage à cause d’une exception ReceiverCallNotAllowedException. Ces pannes se produisent sur un large éventail de versions d’Android de l’API 15 à 22. https://possiblemobile.com/2013/06/context/#comment-2443283153
Car il n’est pas garanti que toutes les opérations décrites comme sockets en charge par le contexte d’application dans le tableau ci-dessous fonctionnent sur tous les appareils Android!