Diferencia entre contexto de actividad y contexto de aplicación

233

Esto me tiene perplejo, estaba usando esto en Android 2.1-r8 SDK:

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

y también en

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

usando getApplicationContext()bloqueos tanto ProgressDialogy Toast... que me llevan a esta pregunta:

¿Cuáles son las diferencias reales entre un contexto de actividad y un contexto de aplicación, a pesar de compartir la redacción 'Contexto'?

t0mm13b
fuente
Esto es lo que he encontrado stackoverflow.com/questions/1561803/… ....
t0mm13b
14
Esto debería ayudar a aclarar algunas cosas: Contexto, ¿Qué contexto?
toobsco42

Respuestas:

250

Ambas son instancias de contexto , pero la instancia de la aplicación está vinculada al ciclo de vida de la aplicación, mientras que la instancia de Activity está vinculada al ciclo de vida de una Actividad. Por lo tanto, tienen acceso a información diferente sobre el entorno de la aplicación.

Si lees los documentos en getApplicationContext , observa que solo debe usar esto si necesita un contexto cuyo ciclo de vida esté separado del contexto actual. Esto no se aplica en ninguno de sus ejemplos.

El contexto de la actividad presumiblemente tiene alguna información sobre la actividad actual que es necesaria para completar esas llamadas. Si muestra el mensaje de error exacto, podría señalar exactamente lo que necesita.

Pero en general, use el contexto de la actividad a menos que tenga una buena razón para no hacerlo.

Cheryl Simon
fuente
1
Obtuve una 'java.lang.reflect.InvocationTargetException' cuando utilicé getApplicationContext, curiosamente, cuando cambié a this, no se bloqueó y funcionó como se esperaba ... así que si ambas son instancias de Context, ¿por qué uno no funciona y el otro hace? Espero que esta información sea de ayuda para otros ... :) gracias por su pronta respuesta ...
t0mm13b
2
Necesitaría ver la excepción completa stacktrace para poder decir algo. Sin embargo, como dije, las instancias de contexto tienen información diferente. Presumiblemente para mostrar un cuadro de diálogo o un brindis en la pantalla se requiere información sobre la Actividad que solo tiene la instancia de Actividad.
Cheryl Simon el
74
Yo diría que use el contexto de la aplicación a menos que tenga una buena razón para no hacerlo (es decir, para diálogos o brindis). Es bastante fácil encontrarse con pérdidas de memoria utilizando contextos de actividad en diferentes situaciones, así que es mejor estar seguro :) android-developers.blogspot.com/2009/01/…
Dori
10
Dave Smith ha publicado una muy buena entrada de blog para comprender el uso del contexto, ver aquí . ¡Asegúrate de leer también los comentarios!
ChrLipp
1
La cuestión es que incluso Dianna Hackborn recomienda usar el contexto de actividad. stackoverflow.com/questions/5228160/… Pero ella parece no estar totalmente segura de esto.
JacksOnF1re
178

Encontré esta tabla súper útil para decidir cuándo usar diferentes tipos de Contextos:

ingrese la descripción de la imagen aquí

  1. Una aplicación PUEDE iniciar una Actividad desde aquí, pero requiere que se cree una nueva tarea. Esto puede ajustarse a casos de uso específicos, pero puede crear comportamientos de back stack no estándar en su aplicación y generalmente no se recomienda ni se considera una buena práctica.
  2. Esto es legal, pero la inflación se realizará con el tema predeterminado para el sistema en el que se está ejecutando, no lo que está definido en su aplicación.
  3. Se permite si el receptor es nulo, que se utiliza para obtener el valor actual de una transmisión fija, en Android 4.2 y superior.

Artículo original aquí .

CommonSenseCode
fuente
¿Qué hay de obtener los recursos? Creo que es mejor que lo sumes a tu mesa. y puede acceder a recursos con contexto de aplicación.
Amir Ziarati
Podemos comenzar la actividad desde el contexto de la aplicación
Duy Phan
El artículo también se puede encontrar aquí: wundermanthompsonmobile.com/2013/06/context
Lifes
34

Obviamente, esto es una deficiencia del diseño de la API. En primer lugar, el contexto de la actividad y el contexto de la aplicación son objetos totalmente diferentes, por lo que los parámetros del método donde se usa el contexto deben usar ApplicationContexto Activitydirectamente, en lugar de usar el contexto de la clase principal. En segundo lugar, el documento debe especificar qué contexto usar o no explícitamente.

lucas
fuente
25
Completamente de acuerdo. Google dejó caer la pelota sobre este. Es un completo desastre.
Søren Boisen
@ SørenBoisen android sdk es un completo desastre
CommonSenseCode
Son conscientes del desorden, y estoy seguro de que están luchando por arreglar todo lo que pueden.
Pasignature
15

La razón por la que creo es que ProgressDialogse adjunta a la actividad que apuntala, ProgressDialogya que el diálogo no puede permanecer después de que la actividad se destruye, por lo que debe pasarse this(ActivityContext) que también se destruye con la actividad, mientras que el ApplicationContext permanece incluso después de que la actividad se destruye. destruido.

usuario2779311
fuente
3

Use getApplicationContext () si necesita algo vinculado a un contexto que tendrá un alcance global.

Si usa Actividad, la nueva instancia de Actividad tendrá una referencia, que tiene una referencia implícita a la Actividad anterior, y la Actividad anterior no se puede recolectar basura.

Dhiraj Himani
fuente
2

Creo que cuando todo necesita una pantalla para mostrar (botón, diálogo, diseño ...) tenemos que usar la actividad de contexto, y todo no necesita una pantalla para mostrar o procesar (tostadas, teléfono de servicio, contacto ...) podría usar un contexto de aplicación

Dmobile
fuente
1

Puede ver una diferencia entre los dos contextos cuando inicia su aplicación directamente desde la pantalla de inicio frente a cuando su aplicación se inicia desde otra aplicación a través de la intención de compartir.

Aquí, un ejemplo práctico de lo que significa "comportamientos de pila no estándar", mencionado por @CommonSenseCode, significa:

Supongamos que tiene dos aplicaciones que se comunican entre sí, App1 y App2 .

Inicie App2: MainActivity desde el iniciador . Luego, desde MainActivity, inicie App2: SecondaryActivity . Allí, ya sea usando el contexto de actividad o el contexto de la aplicación, ambas actividades viven en la misma tarea y esto está bien (dado que usa todos los modos de inicio estándar y marcas de intención). Puede volver a MainActivity presionando hacia atrás y en las aplicaciones recientes solo tiene una tarea.

Supongamos ahora que está en la Aplicación1 e inicie la Aplicación2: MainActivity con una intención de compartir (ACTION_SEND o ACTION_SEND_MULTIPLE). Luego, a partir de ahí, intente iniciar App2: SecondaryActivity (siempre con todos los modos de inicio estándar e indicadores de intención). Lo que sucede es:

  • si inicia App2: SecondaryActivity con contexto de aplicación en Android <10, no puede iniciar todas las actividades en la misma tarea . He intentado con Android 7 y 8 y SecondaryActivity siempre se inicia en una nueva tarea (supongo que es porque App2: SecondaryActivity se inicia con el contexto de la aplicación App2, pero vienes de App1 y no iniciaste la aplicación App2 directamente Quizás, bajo el capó, Android lo reconozca y use FLAG_ACTIVITY_NEW_TASK). Esto puede ser bueno o malo dependiendo de sus necesidades, ya que mi aplicación fue mala.
    En Android 10, la aplicación se bloquea con el mensaje
    "Llamar a startActivity () desde fuera de un contexto de Actividad requiere el indicador FLAG_ACTIVITY_NEW_TASK. ¿Es esto realmente lo que quieres?".
    Entonces, para que funcione en Android 10, debe usar FALG_ACTIVITY_NEW_TASK y no puede ejecutar todas las actividades en la misma tarea.
    Como puede ver, el comportamiento es diferente entre las versiones de Android, raro.

  • si inicia App2: SecondaryActivity con el contexto de actividad, todo va bien y puede ejecutar todas las actividades en la misma tarea, lo que resulta en una navegación lineal de backstack.

Espero haber agregado alguna información útil

DSoldo
fuente