¿Cuándo llamar al contexto de la actividad O contexto de la aplicación?

Ha habido un montón de publicar sobre lo que estos dos contextos son .. Pero todavía no lo estoy haciendo muy bien

Como yo lo entiendo hasta el momento: Cada una es una instancia de su clase, lo que significa que algunos programadores le recomendamos que use this.getApplicationContext() tan a menudo como sea posible con el fin de no "escape" de cualquier memoria. Esto se debe a que el otro (obteniendo el contexto de la instancia de Activity ) apunta a una Activity que se está destruyendo cada vez que el usuario inclina el teléfono o deja la aplicación etc. Lo que aparentemente el Recolector de Basura no captura y por lo tanto usa Demasiada memoria

¿Pero puede alguien por favor venir con algunos ejemplos de codificación muy buenos donde sería la cosa correcta para usar this (obtener el contexto de la instancia actual de la Activity ) y el contexto de la aplicación será inútil / mal?

getApplicationContext() casi siempre es incorrecto. La Sra. Hackborn (entre otras) ha sido muy explícita de que sólo usas getApplicationContext() cuando sabes por qué usas getApplicationContext() y solo cuando necesitas usar getApplicationContext() .

Para ser contundente, "algunos programadores" utilizan getApplicationContext() (o getBaseContext() , en menor medida) porque su experiencia en Java es limitada. Implementan una clase interna (por ejemplo, un OnClickListener para un Button en una Activity ) y necesitan un Context . En lugar de usar MyActivity.this para obtener en la clase externa ' this , utilizan getApplicationContext() o getBaseContext() para obtener un objeto Context .

Sólo utiliza getApplicationContext() cuando sabe que necesita un Context para algo que puede vivir más tiempo que cualquier otro Context probable que tenga a su disposición. Los escenarios incluyen:

  • Use getApplicationContext() si necesita algo vinculado a un Context que por sí mismo tendrá alcance global. Utilizo getApplicationContext() , por ejemplo, en WakefulIntentService , para que el WakeLock estático se utilice para el servicio. Dado que WakeLock es estático, y necesito un Context para llegar a PowerManager para crearlo, es más seguro usar getApplicationContext() .

  • Utilice getApplicationContext() cuando vincula a un Service de una Activity , si desea pasar la ServiceConnection (es decir, el identificador a la vinculación) entre instancias de Activity través de onRetainNonConfigurationInstance() . Android internamente rastrea enlaces a través de estas ServiceConnections y contiene referencias a los Contexts que crean los enlaces. Si vincula desde la Activity , la nueva instancia de Activity tendrá una referencia a la ServiceConnection que tiene una referencia implícita a la antigua Activity , y la antigua Activity no se puede recolectar basura.

Algunos desarrolladores usan subclases personalizadas de Application para sus propios datos globales, que recuperan a través de getApplicationContext() . Eso es ciertamente posible. Prefiero los miembros de datos estáticos, si no por otra razón que sólo puede tener un objeto de Application personalizada. Construí una aplicación utilizando un objeto Application personalizado y encontré que era doloroso. La Sra. Hackborn también está de acuerdo con esta posición .

Aquí hay razones para no usar getApplicationContext() donde quiera que vaya:

  • No es un Context completo, apoyando todo lo que hace la Activity . Varias cosas que intentarás hacer con este Context fallarán, principalmente relacionadas con la GUI .

  • Puede crear fugas de memoria, si el Context de getApplicationContext() mantiene en algo creado por las llamadas en él que no limpia. Con una Activity , si se mantiene en algo, una vez que la Activity recibe la basura recogida, todo lo demás se vacía también. El objeto Application permanece durante toda la vida de su proceso.

Creo que hay un montón de cosas que está mal documentado en el sitio SDK, este es uno de ellos. La afirmación que voy a hacer es que parece que es mejor usar el contexto de la aplicación y usar un contexto de actividad cuando realmente lo necesites. El único lugar donde he visto que necesitas un contexto de actividad es para un diálogo de progreso. SBERG412 afirma que tiene que utilizar un contexto de actividad para un mensaje de brindis, pero los documentos de Android muestran claramente un contexto de aplicación que se utiliza. Siempre he utilizado el contexto de aplicación para brindis debido a este ejemplo de Google. Si está mal hacerlo, entonces Google dejó caer el balón aquí.

Aquí hay más cosas que pensar y revisar:

Para un mensaje de brindis, la Guía de Google Dev utiliza el contexto de la aplicación y dice explícitamente que debe usarlo: Notificaciones Toast

En la sección de diálogos de la guía Dev, verá que un AlertDialog.Builder utiliza el contexto de la aplicación y, a continuación, la barra de progreso utiliza un contexto de actividad. Esto no se explica por Google. Diálogos

Parece que una buena razón para utilizar el contexto de la aplicación es cuando desea manejar cambios de configuración como un cambio de orientación y desea conservar objetos que necesitan un contexto como Vistas. Si miras aquí: Run Time Changes Hay una advertencia sobre el uso de un contexto de actividad, que puede crear una fuga. Esto se puede evitar con un contexto de aplicación con las opiniones que deben ser retenidas (al menos eso es lo que entiendo). En una aplicación que estoy escribiendo, tengo la intención de utilizar un contexto de aplicación porque estoy tratando de mantener algunas vistas y otras cosas en un cambio de orientación, y todavía quiero que la actividad se destruya y se recrea en los cambios de orientación. Por lo tanto, tengo que usar un contexto de aplicación para no causar una pérdida de memoria (consulte Evitar fugas de memoria ). A mi me parece que hay un montón de buenas razones para utilizar el contexto de la aplicación en lugar de un contexto de actividad, y para mí casi parece que lo utilizaría más a menudo que un contexto de actividad. Eso es lo que muchos libros de Android que he pasado parecen hacer, y eso es lo que muchos de los ejemplos de Google que he visto hacer.

La documentación de Google realmente hace que parezca que usar el contexto de la aplicación está perfectamente bien en la mayoría de los casos, y de hecho aparece más a menudo que usar un contexto de actividad en sus ejemplos (al menos los ejemplos que he visto). Si realmente es un problema usar el contexto de la aplicación, entonces Google realmente necesita poner más énfasis en esto. Necesitan dejarlo claro, y necesitan rehacer algunos de sus ejemplos. Yo no culparía esto totalmente a los desarrolladores sin experiencia, ya que la autoridad (Google) realmente hace que parezca que no es un problema para usar contextos de aplicación.

Acabo de utilizar esta tabla como una guía para cuando utilizar los diferentes tipos de Contexto como el contexto de la aplicación (es decir: getApplicationContext() ) y el contexto de la actividad , también BroadcastReceiver contexto :

Introduzca aquí la descripción de la imagen

Artículo original aquí para más información.

¿Qué contexto usar?

Hay dos tipos de Contexto:

  1. El contexto de la aplicación se asocia con la aplicación y siempre será el mismo durante toda la vida de la aplicación – no cambia. Por lo tanto, si utiliza Toast, puede utilizar el contexto de la aplicación o incluso el contexto de la actividad (ambos) porque la tostada puede mostrarse desde cualquier lugar de la aplicación y no está asociada a una ventana específica. Pero hay muchas excepciones, una excepción es cuando se necesita usar o pasar el contexto de la actividad.

  2. El contexto de la actividad está asociado con la actividad y puede ser destruido si la actividad es destruida – puede haber múltiples actividades (más que probable) con una sola aplicación. Y a veces es absolutamente necesario el identificador de contexto de actividad. Por ejemplo, si inicia una nueva actividad, debe utilizar el contexto de la actividad en su Intención para que la nueva actividad de lanzamiento se conecte a la actividad actual en términos de pila de actividades. Sin embargo, también puede utilizar el contexto de la aplicación para iniciar una nueva actividad, pero debe establecer el indicador Intent.FLAG_ACTIVITY_NEW_TASK con la intención de tratarlo como una nueva tarea.

Consideremos algunos casos:

  • MainActivity.this refiere al contexto MainActivity que extiende la clase Activity pero la clase base (activity) también extiende la clase Context, por lo que se puede utilizar para ofrecer el contexto de la actividad.

  • getBaseContext() ofrece un contexto de actividad.

  • getApplication() ofrece un contexto de aplicación.

  • getApplicationContext() también ofrece contexto de aplicación.

Para obtener más información, consulte este enlace .

Dos grandes ejemplos de cuándo debe utilizarse el contexto de la actividad en comparación con el contexto de la aplicación son cuando se muestra un mensaje Toast o un mensaje de diálogo incorporado como utilizar el contexto de la aplicación provocará una excepción:

 ProgressDialog.show(this, ....); 

o

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

Ambos necesitan información del contexto de la actividad que no se proporciona en el contexto de la aplicación.

Contexto de la aplicación en vivo hasta que su aplicación sólo está viva y no depende del ciclo de vida de la actividad pero, el objeto de mantener el contexto de larga vida . Si el objeto que se utiliza temporalmente, ese uso de tiempo Contexto de la Aplicación y Contexto de la actividad se utiliza totalmente opuesto al Contexto de la Aplicación.

Me preguntaba por qué no utilizar el contexto de aplicación para cada operación que admite. Al final, disminuye la probabilidad de pérdida de memoria y falta la comprobación nula de getContext () o getActivity () (cuando se utiliza el contexto de aplicación inyectado o se adquiere mediante el método estático de Application). Declaraciones, como la de la Sra. Hackborn para usar el Contexto de la Aplicación sólo si es necesario, no me parecen convincentes sin una explicación de por qué. Pero parece que he encontrado un unswear por qué:

Han encontrado que hay problemas en algunas combinaciones de versión / dispositivo de Android que no siguen estas reglas. Por ejemplo, si tengo un BroadcastReceiver que se pasa un Contexto y convertir ese Contexto a un Contexto de Aplicación y luego intento llamar a registerReceiver () en el Contexto de la Aplicación hay muchos casos en los que esto funciona bien, pero también muchas instancias donde recibo Un bloqueo debido a un ReceiverCallNotAllowedException. Estos bloqueos se producen en una amplia gama de versiones de Android desde API 15 hasta 22. https://possiblemobile.com/2013/06/context/#comment-2443283153

¡Porque no está garantizado que todas las operaciones descritas como soportadas por el Contexto de la Aplicación en la tabla siguiente funcionarán en todos los dispositivos Android! Introduzca aquí la descripción de la imagen

  • Android - Cómo utilizar ORMLite dbhelper para todo el ciclo de vida de la aplicación
  • No es accesible en el contexto actual
  • Cómo funciona SQLiteOpenHelper Context
  • ¿Por qué FileOutputStream lanzar FileNotFoundException?
  • ¿Cómo mostrar AlertDialog en un fragmento?
  • Pasando referencia a la actividad a la clase de utilidad android
  • ¿Cómo llamar al método de otra clase sin pasar el contexto?
  • Mimic Context.getExternalFilesDir () antes de Android API Nivel 8?
  • ¿Cómo obtener el contexto de una actividad extendiendo ListFragment desde su clase de adaptador?
  • Android Contexto Referencia débil
  • ¿Puede alguien aclarar las referencias al contexto de Android?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.