Diferença entre Contexto de Atividade e Contexto de Aplicativo

233

Isso me deixou perplexo, eu estava usando isso no Android 2.1-r8 SDK:

ProgressDialog.show(getApplicationContext(), ....);

e também em

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

usando getApplicationContext()falhas tanto ProgressDialoge Toast.... o que me levou a esta pergunta:

Quais são as diferenças reais entre um contexto de atividade e um contexto de aplicativo, apesar de compartilhar o texto 'Contexto'?

t0mm13b
fonte
Isto é o que eu encontrei stackoverflow.com/questions/1561803/… .... #
t0mm13b
14
Isso deve ajudar a esclarecer algumas coisas: Contexto, que contexto?
toobsco42

Respostas:

250

Ambas são instâncias do Contexto , mas a instância do aplicativo está vinculada ao ciclo de vida do aplicativo, enquanto a instância do Activity está vinculada ao ciclo de vida de uma Atividade. Assim, eles têm acesso a informações diferentes sobre o ambiente do aplicativo.

Se você ler os documentos em getApplicationContext , observe que você deve usá-lo apenas se precisar de um contexto cujo ciclo de vida seja separado do contexto atual. Isso não se aplica a nenhum dos seus exemplos.

O contexto de atividade presumivelmente possui algumas informações sobre a atividade atual necessária para concluir essas chamadas. Se você mostrar a mensagem de erro exata, poderá apontar para o que exatamente é necessário.

Mas, em geral, use o contexto da atividade, a menos que você tenha um bom motivo para não fazê-lo.

Cheryl Simon
fonte
1
Eu recebi um 'java.lang.reflect.InvocationTargetException' ao usar getApplicationContext, curiosamente, quando mudei para this, ele não travou e funcionou conforme o esperado ... então, se são as duas instâncias do contexto, por que não funciona e o outro faz? Esta informação vai ser de ajuda para os outros que eu espero ... :) Obrigado pela sua resposta rápida ...
t0mm13b
2
Eu precisaria ver o rastreamento de pilha de exceção completo para poder dizer qualquer coisa. No entanto, como eu disse, as instâncias de contexto têm informações diferentes. Presumivelmente, mostrar uma caixa de diálogo ou um brinde na tela requer informações sobre a Atividade que somente a instância da Atividade possui.
Cheryl Simon
74
Eu diria que use o contexto do aplicativo, a menos que você também não tenha um bom motivo (ou seja, para diálogos ou brindes). É bastante fácil de executar em vazamentos de memória, utilizando contextos de atividade em diferentes situações de modo melhor para ser seguro :) android-developers.blogspot.com/2009/01/...
Dori
10
Dave Smith postou uma entrada de blog muito boa para entender o uso do contexto, veja aqui . Leia também os comentários!
precisa saber é o seguinte
1
O fato é que mesmo Dianna Hackborn recomenda usar o contexto de atividade. stackoverflow.com/questions/5228160/… Mas ela parece não ter muita certeza disso.
JacksOnF1re
178

Achei esta tabela super útil para decidir quando usar diferentes tipos de contextos:

insira a descrição da imagem aqui

  1. Um aplicativo PODE iniciar uma Atividade a partir daqui, mas requer que uma nova tarefa seja criada. Isso pode se encaixar em casos de uso específicos, mas pode criar comportamentos de pilha não padronizada em seu aplicativo e geralmente não é recomendado ou considerado uma boa prática.
  2. Isso é legal, mas a inflação será feita com o tema padrão do sistema no qual você está executando, não com o que está definido no seu aplicativo.
  3. Permitido se o receptor for nulo, usado para obter o valor atual de uma transmissão persistente, no Android 4.2 e superior.

Artigo original aqui .

CommonSenseCode
fonte
que tal obter os recursos? acho melhor você adicioná-lo à sua mesa. e você pode acessar recursos com o contexto de aplicação.
Amir Ziarati
Podemos começar a atividade a partir do contexto de aplicação
Duy Phan
Artigo também pode ser encontrado aqui: wundermanthompsonmobile.com/2013/06/context
Lifes
34

Obviamente, isso é deficiência do design da API. Em primeiro lugar, o contexto da atividade e o contexto do aplicativo são objetos totalmente diferentes; portanto, os parâmetros do método em que o contexto é usado devem usar ApplicationContextou Activitydiretamente, em vez de usar a classe pai Context. Em segundo lugar, o documento deve especificar qual contexto usar ou não explicitamente.

lucas
fonte
25
Totalmente de acordo. O Google deixou cair a bola nessa. É uma bagunça completa.
Søren Boisen
@ SørenBoisen Android SDK é uma bagunça completa
CommonSenseCode
Eles estão cientes da bagunça e tenho certeza de que estão se esforçando bastante para consertar o máximo possível.
pasignature 17/06
15

A razão pela qual penso é que ProgressDialogestá anexado à atividade que sustenta o argumento, ProgressDialogpois o diálogo não pode permanecer após a atividade ser destruída, por isso precisa ser passado this(ActivityContext) que também é destruído com a atividade, enquanto o ApplicationContext permanece mesmo após a atividade ser destruída. destruído.

user2779311
fonte
3

Use getApplicationContext () se precisar de algo vinculado a um Contexto que tenha escopo global.

Se você usar a Atividade, a nova instância da Atividade terá uma referência, que tem uma referência implícita à Atividade antiga, e a Atividade antiga não poderá ser coletada como lixo.

Dhiraj Himani
fonte
2

Acho que quando tudo precisa ser exibido em uma tela (botão, caixa de diálogo, layout ...) precisamos usar a atividade de contexto, e tudo não precisa de uma tela para mostrar ou processar (brinde, telefone, telefone, contato ...) poderia usar um contexto de aplicativo

Dmobile
fonte
1

Você pode ver uma diferença entre os dois contextos quando você inicia o aplicativo diretamente na tela inicial e quando o aplicativo é iniciado a partir de outro aplicativo por meio do compartilhamento.

Aqui está um exemplo prático do que significa "comportamentos de pilha não padronizada", mencionados por @CommonSenseCode, significa:

Suponha que você tenha dois aplicativos que se comunicam, App1 e App2 .

Inicie o App2: MainActivity a partir do iniciador. Em MainActivity, inicie o App2: SecondaryActivity . Lá, usando o contexto de atividade ou o contexto do aplicativo, ambas as atividades vivem na mesma tarefa e isso é aceitável (desde que você use todos os modos de inicialização padrão e sinalizadores de intenção). Você pode voltar ao MainActivity pressionando novamente e nos aplicativos recentes você tem apenas uma tarefa.

Suponha agora que você esteja no App1 e inicie o App2: MainActivity com uma intenção de compartilhamento (ACTION_SEND ou ACTION_SEND_MULTIPLE). Em seguida, tente iniciar o App2: SecondaryActivity (sempre com todos os modos de inicialização padrão e sinalizadores de intenção). O que acontece é:

  • se você iniciar App2: SecondaryActivity com contexto de aplicativo no Android <10, não poderá iniciar todas as atividades na mesma tarefa . Eu tentei com o Android 7 e 8 e o SecondaryActivity sempre é iniciado em uma nova tarefa (acho que é porque o App2: SecondaryActivity é iniciado com o contexto do aplicativo App2, mas você é do App1 e não iniciou o aplicativo App2 diretamente Talvez por baixo do capô o Android reconheça isso e use FLAG_ACTIVITY_NEW_TASK). Isso pode ser bom ou ruim, dependendo de suas necessidades, pois meu aplicativo foi ruim.
    No Android 10, o aplicativo trava com a mensagem
    "Chamar startActivity () de fora de um contexto de Atividade requer o sinalizador FLAG_ACTIVITY_NEW_TASK. É isso mesmo que você deseja?" .
    Portanto, para fazê-lo funcionar no Android 10, você precisa usar o FALG_ACTIVITY_NEW_TASK e não pode executar todas as atividades na mesma tarefa.
    Como você pode ver, o comportamento é diferente entre as versões do Android, estranho.

  • se você iniciar App2: SecondaryActivity com o contexto de atividade, tudo correrá bem e você poderá executar todas as atividades na mesma tarefa, resultando em uma navegação linear de backstack.

Espero ter adicionado algumas informações úteis

DSoldo
fonte