web-dev-qa-db-fra.com

getApplication () vs getApplicationContext ()

Je ne trouvais pas de réponse satisfaisante à cela, alors allons-y: quel est le problème avec Activity/Service.getApplication() et Context.getApplicationContext()?

Dans notre application, les deux renvoient le même objet. Dans un ActivityTestCase cependant, si vous vous moquez de l'application, getApplication() reviendra avec la maquette, mais getApplicationContext renverra toujours une instance de contexte différente (injectée par Android). Est-ce un bug? Est-ce délibéré?

Je ne comprends même pas la différence en premier lieu. Existe-t-il des cas en dehors d'une suite de tests où les deux appels peuvent revenir avec des objets différents? Quand et pourquoi De plus, pourquoi getApplication est-il défini sur Activity et Service, mais pas sur Context? Ne devrait-il pas toujours y avoir une instance d'application valide disponible à partir de n'importe où?

401
Matthias

Question très intéressante. Je pense que c'est principalement un sens sémantique, et peut aussi être dû à des raisons historiques.

Bien que, dans les implémentations actuelles de Android Activity et Service, getApplication() et getApplicationContext() renvoient le même objet, rien ne garantit que cela sera toujours le cas (par exemple, chez un fournisseur spécifique). la mise en oeuvre).

Donc, si vous voulez que la classe d’application que vous avez enregistrée dans le manifeste, vous devez jamais appeler getApplicationContext() et l’envoyer dans votre application, car il ne s’agit peut-être pas de l’instance d’application le cadre de test).

Pourquoi getApplicationContext() existe-t-il en premier lieu?

getApplication() n'est disponible que dans les classes Activity et Service, alors que getApplicationContext() est déclaré dans la classe Context.

En réalité, cela signifie une chose: lors de l'écriture de code dans un récepteur de diffusion, ce qui n'est pas un contexte mais un contexte dans sa méthode onReceive, vous ne pouvez appeler que getApplicationContext(). Cela signifie également que vous n'êtes pas assuré d'avoir accès à votre application dans un BroadcastReceiver.

Lorsque vous examinez le code Android, vous voyez que, lorsqu'elle est attachée, une activité reçoit un contexte de base et une application, et ces paramètres sont différents. getApplicationContext() délègue son appel à baseContext.getApplicationContext().

Une dernière chose: la documentation indique que dans la plupart des cas, vous ne devriez pas avoir besoin de sous-classe Application:

Il n’est normalement pas nécessaire de sous-classe Application. Dans la plupart des cas, les singletons statiques peuvent fournir les mêmes fonctionnalités de manière plus modulaire. Si votre singleton a besoin d'un contexte global (par exemple pour enregistrer des récepteurs de diffusion), la fonction permettant de le récupérer peut recevoir un Context qui utilise en interne Context.getApplicationContext() lors de la première construction du singleton.

Je sais que ce n’est pas une réponse exacte et précise, mais cela répond-il à votre question?

356
Pierre-Yves Ricau

Comparez getApplication() et getApplicationContext() .

getApplication renvoie un objet Application qui vous permettra de gérer l'état général de votre application et de réagir à certaines situations de périphérique, telles que onLowMemory() et onConfigurationChanged() .

getApplicationContext renvoie le contexte global de l'application. La différence par rapport aux autres contextes est que, par exemple, un contexte d'activité peut être détruit (ou rendu indisponible, autrement) par Android à la fin de votre activité. Le contexte d’application reste disponible tant que votre objet d’application existe (il n’est pas lié à un Activity spécifique). Vous pouvez donc l'utiliser pour des éléments tels que Notifications qui nécessitent un contexte qui sera disponible pendant de plus longues périodes. indépendant des objets UI transitoires.

J'imagine que cela dépend de ce que votre code fait pour savoir si ceux-ci peuvent être ou non identiques - bien qu'en utilisation normale, je m'attende à ce qu'ils soient différents.

31
RivieraKid

Cela semble avoir à voir avec le wrapping contextuel. La plupart des classes dérivées de Context sont en fait un ContextWrapper , qui délègue essentiellement à un autre contexte, éventuellement avec des modifications par le wrapper.

Le contexte est une abstraction générale qui prend en charge les moqueries et les mandataires. Étant donné que de nombreux contextes sont liés à un objet à durée de vie limitée tel qu'un Activity , il doit exister un moyen d'obtenir un contexte plus long tels que l'enregistrement pour les notifications futures. Ceci est réalisé par Context.getApplicationContext() . Une implémentation logique consiste à renvoyer l'objet global Application , mais rien n'empêche une implémentation en contexte de renvoyer un wrapper ou un proxy avec une durée de vie appropriée.

Les activités et les services sont plus spécifiquement associés à un objet Application . Je pense que l’utilité de cela est que vous pouvez créer et inscrire dans le manifeste une classe personnalisée dérivée de Application et vous assurer que Activity.getApplication() ou Service.getApplication() renvoie cet objet spécifique de ce type spécifique, que vous pouvez attribuer à votre classe dérivée Application et utiliser à quelque fin que ce soit.

En d'autres termes, getApplication() est garanti pour renvoyer un objet Application, alors que getApplicationContext() est libre de renvoyer un proxy à la place.

29
usethe4ce