getApplicationContext()
quase sempre está errado. Hackborn (entre outros) tem sido muito explícita que você só usa getApplicationContext()
quando sabe por que está usando getApplicationContext()
e somente quando precisa usá-lo getApplicationContext()
.
Para ser franco, "alguns programadores" usam getApplicationContext()
(ou getBaseContext()
, em menor grau) porque sua experiência em Java é limitada. Eles implementam uma classe interna (por exemplo, um OnClickListener
para um Button
em um Activity
) e precisam de um Context
. Em vez de usar MyActivity.this
para chegar à classe externa ' this
, eles usam getApplicationContext()
ou getBaseContext()
para obter um Context
objeto.
Você só usa getApplicationContext()
quando sabe que precisa Context
de algo que pode durar mais tempo do que qualquer outro que possa Context
ter à sua disposição. Os cenários incluem:
Use getApplicationContext()
se você precisar de algo vinculado a um Context
que tenha escopo global. Eu uso getApplicationContext()
, por exemplo, em WakefulIntentService
, para a estática WakeLock
a ser usada para o serviço. Desde que WakeLock
é estático, e eu preciso de um Context
para chegar a PowerManager
criá-lo, é mais seguro de usar getApplicationContext()
.
Use getApplicationContext()
quando você ligar a um Service
de um Activity
, se desejar passar o ServiceConnection
(ou seja, o identificador para o vínculo) entre Activity
instâncias via onRetainNonConfigurationInstance()
. O Android rastreia internamente as ligações por meio delas ServiceConnections
e mantém referências àquelas Contexts
que criam as ligações. Se você ligar a partir de Activity
, a nova Activity
instância terá uma referência à ServiceConnection
que possui uma referência implícita à antiga Activity
, e a antiga Activity
não poderá ser coletada como lixo.
Alguns desenvolvedores usam subclasses personalizadas Application
para seus próprios dados globais, dos quais eles recuperam getApplicationContext()
. Isso é certamente possível. Prefiro membros de dados estáticos, se por nenhum outro motivo, você puder ter apenas umApplication
objeto personalizado . Criei um aplicativo usando um Application
objeto personalizado e achei doloroso. Hackborn também concorda com esta posição .
Aqui estão as razões pelas quais não usar getApplicationContext()
onde quer que você vá:
Não é um completo Context
, suportando tudo o que Activity
faz. Várias coisas que você tentará fazer com isso Context
falharão, principalmente relacionadas à GUI .
Ele pode criar vazamentos de memória, se o Context
from se getApplicationContext()
apegar a algo criado por suas chamadas que você não limpa. Com um Activity
, se ele se agarra a alguma coisa, uma vez que o Activity
lixo é coletado, todo o resto também sai. O Application
objeto permanece durante toda a vida útil do seu processo.
getApplicationContext()
quando sabe exatamente por que precisa dele em uma determinada situação. Inflar um layout? Use a atividade. Ligação a um serviço, onde você precisa dessa ligação para sobreviver a uma alteração na configuração? UsegetApplicationContext()
, para que a ligação não esteja vinculada àActivity
instância.Acho que há muitas coisas mal documentadas no site do SDK, essa é uma delas. A afirmação que vou fazer é que parece melhor usar como padrão um contexto de aplicativo e usar apenas um contexto de atividade quando você realmente precisar. O único lugar em que eu já vi que você precisa de um contexto de atividade é para uma caixa de diálogo de progresso. SBERG412 alega que você precisa usar um contexto de atividade para uma mensagem de brinde, mas os documentos do Android mostram claramente um contexto de aplicativo que está sendo usado. Eu sempre usei o contexto do aplicativo para brindes por causa deste exemplo do Google. Se estiver errado, o Google largou a bola aqui.
Aqui está mais para pensar e analisar:
Para uma mensagem de brinde, o Guia do desenvolvedor do Google usa o contexto do aplicativo e diz explicitamente para usá-lo: Notificações de brinde
Na seção de diálogos do guia Dev, você vê que um AlertDialog.Builder usa o contexto do aplicativo e, em seguida, a barra de progresso usa um contexto de atividade. Isso não é explicado pelo Google. Diálogos
Parece que um bom motivo para usar o contexto do aplicativo é quando você deseja lidar com alterações de configuração como uma mudança de orientação e deseja manter objetos que precisam de um contexto como Views. Se você olhar aqui: Alterações no tempo de execução Há um cuidado ao usar um contexto de atividade, que pode criar um vazamento. Isso pode ser evitado com um contexto de aplicativo com as visualizações que devem ser mantidas (pelo menos, esse é o meu entendimento). Em um aplicativo que estou escrevendo, pretendo usar um contexto de aplicativo porque estou tentando adiar algumas visualizações e outras coisas em uma mudança de orientação, e ainda quero que a atividade seja destruída e recriada em alterações de orientação. Portanto, tenho que usar um contexto de aplicativo para não causar vazamento de memória (consulte Evitando vazamentos de memória) Para mim, parece haver muitas boas razões para usar o contexto do aplicativo em vez de um contexto de atividade, e para mim parece que você usaria com mais frequência do que um contexto de atividade. É o que muitos livros do Android que eu já passei parecem fazer, e é o que muitos dos exemplos do Google que eu já vi fazer.
A documentação do Google realmente parece que o uso do contexto do aplicativo é perfeitamente adequado na maioria dos casos e, na verdade, aparece com mais frequência do que o uso do contexto de atividade em seus exemplos (pelo menos nos exemplos que eu já vi). Se é realmente um problema usar o contexto do aplicativo, o Google realmente precisa colocar mais ênfase nisso. Eles precisam deixar claro e refazer alguns de seus exemplos. Eu não culparia isso inteiramente por desenvolvedores inexperientes, já que a autoridade (Google) realmente parece que não é um problema usar contextos de aplicativos.
fonte
Usei esta tabela como uma orientação para quando usar os diferentes tipos de contexto, como o contexto de aplicativo (ou seja:)
getApplicationContext()
e o contexto de atividade , também o contexto BroadcastReceiver :Todos os méritos vão para o autor original aqui para mais informações.
fonte
Existem dois tipos de contexto:
O contexto do aplicativo está associado ao aplicativo e sempre será o mesmo durante toda a vida útil do aplicativo - ele não muda. Portanto, se você estiver usando o Toast, poderá usar o contexto do aplicativo ou mesmo o contexto da atividade (ambos) porque o toast pode ser exibido de qualquer lugar do aplicativo e não está anexado a uma janela específica. Mas há muitas exceções, uma delas é quando você precisa usar ou passar no contexto da atividade.
O contexto da atividade está associado à atividade e pode ser destruído se a atividade for destruída - pode haver várias atividades (mais do que provável) com um único aplicativo. E às vezes você absolutamente precisa do identificador do contexto da atividade. Por exemplo, se você iniciar uma nova atividade, precisará usar o contexto da atividade em sua Intenção, para que a nova atividade de inicialização seja conectada à atividade atual em termos de pilha de atividades. No entanto, você também pode usar o contexto do aplicativo para iniciar uma nova atividade, mas precisa definir o sinalizador
Intent.FLAG_ACTIVITY_NEW_TASK
com a intenção de tratá-la como uma nova tarefa.Vamos considerar alguns casos:
MainActivity.this
refere-se ao contexto MainActivity que estende a classe Activity, mas a classe base (atividade) também estende a classe Context, para que possa ser usada para oferecer contexto de atividade.getBaseContext()
oferece contexto de atividade.getApplication()
oferece contexto de aplicativo.getApplicationContext()
também oferece contexto de aplicativo.Para mais informações, consulte este link .
fonte
downloadmanager
e, quando o sinal finalizado é recebido, ele deve exibir uma caixa de diálogo, como "O que você deseja fazer com este download?". Minha solução (hack) salva a mais recenteActivity
de umastatic
Application
classe e solicita a atualActivity
quando o download estiver concluído. No entanto, duvido que esta seja a implementação adequada. TL; DR Como exibir o AlertDialog em qualquer lugar do aplicativo?Fiquei me perguntando por que não usar o Contexto do Aplicativo para todas as operações que ele suporta. No final, reduz a chance de vazamento de memória e falta de verificação nula para getContext () ou getActivity () (ao usar o contexto do aplicativo injetado ou adquirido através do método estático do aplicativo). Declarações, como a da Sra. Hackborn para usar o Contexto do Aplicativo apenas se necessário, não me parecem convincentes sem uma explicação. Mas parece que eu descobri um porquê:
Como não é garantido que todas as operações descritas como suportadas pelo Contexto do aplicativo na tabela abaixo funcionem em todos os dispositivos Android!
fonte
Dois ótimos exemplos de quando você deve usar o contexto de atividade versus o contexto de aplicativo são quando exibir uma mensagem Toast ou uma mensagem de diálogo interna, pois o uso do contexto de aplicativo causará uma exceção:
ou
Ambos precisam de informações do contexto de Atividade que não são fornecidas no contexto de Aplicativo.
fonte
Contexto de aplicação viver até que a sua aplicação está vivo somente e não é depender de Atividade do Ciclo de Vida, mas, contexto objeto keep longa vida . Se o objeto usado temporariamente, esse tempo usar o Contexto do Aplicativo e o Contexto da Atividade será totalmente oposto ao Contexto do Aplicativo.
fonte