android - inicializar - ¿Cuándo llamar al contexto de la actividad o al contexto de la aplicación?
inicializar context (7)
¿Qué contexto usar?
Hay dos tipos de contexto:
El contexto de la aplicación está asociado a la aplicación y siempre será el mismo durante toda la vida de la aplicación, no cambia. Entonces, si está utilizando Toast, puede usar el contexto de la aplicación o incluso el contexto de la actividad (ambos) porque se puede mostrar desde cualquier lugar con su aplicación y no se adjunta a una ventana específica. Pero hay muchas excepciones, una excepción es cuando necesita usar o pasar el contexto de la actividad.
El contexto de la actividad está asociado con la actividad y se puede destruir si se destruye la actividad; puede haber múltiples actividades (lo más probable) con una sola aplicación. Y a veces es absolutamente necesario manejar el contexto de la actividad. Por ejemplo, si inicia una nueva actividad, debe usar el contexto de la actividad en su Intención para que la nueva actividad de lanzamiento esté conectada a la actividad actual en términos de pila de actividad. Sin embargo, también puede usar el contexto de la aplicación para iniciar una nueva actividad, pero luego debe establecer el indicador
Intent.FLAG_ACTIVITY_NEW_TASK
con la intención de tratarla como una nueva tarea.
Consideremos algunos casos:
MainActivity.this
refiere al contexto MainActivity que extiende la clase de actividad, pero la clase base (actividad) también extiende la clase de contexto, por lo que puede usarse para ofrecer contexto de actividad.getBaseContext()
ofrece contexto de actividad.getApplication()
ofrece contexto de aplicación.getApplicationContext()
también ofrece contexto de aplicación.
Para más información por favor revisa este link .
Se ha publicado mucho sobre estos dos contextos ... Pero todavía no lo estoy entendiendo bien
Como lo entiendo hasta ahora: cada una es una instancia de su clase, lo que significa que algunos programadores recomiendan que use this.getApplicationContext()
tan a menudo como sea posible para no "filtrar" ninguna memoria. Esto se debe a que el otro (el contexto de la instancia de la Activity
) apunta a una Activity
que se destruye cada vez que el usuario inclina el teléfono o abandona la aplicación, etc. Lo que aparentemente el recolector de basura (GC) no detecta y, por lo tanto, utiliza demasiada memoria ..
Pero, ¿puede alguien presentar algunos ejemplos de codificación realmente buenos donde sería correcto usar this
(obtener el contexto de la instancia actual de la Activity
) y el contexto de la aplicación será inútil / incorrecto?
Creo que hay muchas cosas que están mal documentadas en el sitio del SDK, esta es una de ellas. La afirmación que voy a hacer es que parece que es mejor usar el contexto de una aplicación y usar solo un contexto de actividad cuando realmente lo necesitas. El único lugar donde he visto que necesita un contexto de actividad es para un diálogo de progreso. SBERG412 afirma que tiene que usar un contexto de actividad para un mensaje de brindis, pero los documentos de Android muestran claramente el contexto de la aplicación que se está utilizando. Siempre he usado el contexto de la aplicación para brindar por este ejemplo de Google. Si está mal hacerlo, entonces Google dejó caer la pelota aquí.
Aquí hay más para pensar y revisar:
Para un mensaje de brindis, la Guía de desarrollo de Google usa el contexto de la aplicación y dice explícitamente para usarlo: Notificaciones de brindis
En la sección de diálogos de la guía de desarrollo, verá que AlertDialog.Builder usa el contexto de la aplicación, y luego la barra de progreso usa un contexto de actividad. Esto no es explicado por Google. Dialogs
Parece que una buena razón para usar 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 mira aquí: Run Time Changes (Cambios de tiempo de ejecución) Existe 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 vistas que se van a conservar (al menos eso es lo que yo entiendo). En una aplicación que estoy escribiendo, tengo la intención de usar un contexto de aplicación porque estoy tratando de mantener algunas vistas y otras cosas sobre un cambio de orientación, y todavía quiero que la actividad se destruya y se vuelva a crear 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 Cómo evitar las fugas de memoria ). Para mí, parece que hay muchas buenas razones para usar el contexto de la aplicación en lugar de un contexto de actividad, y para mí parece que lo usarías más a menudo que un contexto de actividad. Eso es lo que muchos de los libros de Android por los 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. No culparía por completo a los desarrolladores sin experiencia ya que la autoridad (Google) realmente hace que parezca que no es un problema usar contextos de aplicaciones.
Dos grandes ejemplos de cuándo debe usar el contexto de actividad frente al contexto de la aplicación son cuando se muestra un mensaje de Toast o un mensaje de diálogo integrado al usar el contexto de la aplicación causará 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.
Me preguntaba por qué no usar el contexto de aplicación para cada operación que admita. Al final, reduce la posibilidad de pérdida de memoria y falta de comprobación nula para getContext () o getActivity () (cuando se usa un contexto de aplicación inyectado o se adquiere a través del método estático de la aplicación). Las declaraciones, como la de la Sra. Hackborn para usar el contexto de aplicación solo si es necesario, no me parecen convincentes sin una explicación de por qué. Pero parece que he encontrado un desconocimiento 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 al que se pasa un Contexto y lo convierto en un Contexto de la aplicación y luego trato de llamar a registerReceiver () en el Contexto de la aplicación, hay muchos casos en los que esto funciona bien, pero también muchos casos en los que recibo un bloqueo debido a una ReceiverCallNotAllowedException. Estos bloqueos ocurren en una amplia gama de versiones de Android desde API 15 hasta 22. https://possiblemobile.com/2013/06/context/#comment-2443283153
¡Porque no se garantiza que todas las operaciones descritas como compatibles con el contexto de la aplicación en la tabla a continuación funcionarán en todos los dispositivos Android!
Utilicé esta tabla como una guía para cuándo usar los diferentes tipos de contexto, como el contexto de la aplicación (es decir, getApplicationContext()
) y el contexto de la actividad , también el contexto de BroadcastReceiver :
Artículo original here para más información.
getApplicationContext()
casi siempre es incorrecto. La Sra. Hackborn (entre otras) ha sido muy explícito en que solo usa getApplicationContext()
cuando sabe por qué está usando getApplicationContext()
y solo cuando necesita usar getApplicationContext()
.
Para ser franco, "algunos programadores" usan getApplicationContext()
(o getBaseContext()
, en menor medida) porque su experiencia con 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 esto en la clase externa, usan getApplicationContext()
o getBaseContext()
para obtener un objeto Context
.
Solo usa getApplicationContext()
cuando sabe que necesita un Context
para algo que pueda vivir más que cualquier otro Context
probable que tenga a su disposición. Los escenarios incluyen:
Use
getApplicationContext()
si necesita algo vinculado a unContext
que en sí mismo tendrá un alcance global. UtilizogetApplicationContext()
, por ejemplo, enWakefulIntentService
, paraWakeLock
elWakeLock
estático para el servicio. Dado queWakeLock
es estático, y necesito unContext
para acceder aPowerManager
para crearlo, es más seguro usargetApplicationContext()
.Utilice
getApplicationContext()
cuando se enlaza a unService
de unaActivity
, si desea pasar laServiceConnection
(es decir, el identificador al enlace) entre instancias de laActivity
través deonRetainNonConfigurationInstance()
. Android realiza un seguimiento interno de los enlaces a través de estasServiceConnections
y contiene referencias a losContexts
que crean los enlaces. Si se vincula desde laActivity
, entonces la nueva instancia de laActivity
tendrá una referencia a laServiceConnection
que tiene una referencia implícita a laActivity
, y laActivity
no puede ser recogida de 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 usted solo puede tener un objeto de Application
personalizado. Construí una aplicación usando un objeto de Application
personalizado y encontré que era doloroso. La Sra. Hackborn también está de acuerdo con esta posición .
Aquí hay razones por las que no debe usar getApplicationContext()
donde quiera que vaya:
No es un
Context
completo, apoyando todo lo que hace laActivity
. Varias cosas que tratará de hacer con esteContext
fallarán, en su mayoría relacionadas con la GUI .Puede crear fugas de memoria, si el
Context
desdegetApplicationContext()
conserva algo creado por sus llamadas en él que no limpia. Con unaActivity
, si se aferra a algo, una vez que se recolecta la basura, todo lo demás también desaparece. El objetoApplication
permanece durante el tiempo de vida de su proceso.
El contexto de la aplicación en vivo hasta que la aplicación esté activa solo y no depende del ciclo de vida de la actividad, pero el objeto de mantenimiento del contexto es de larga duración . Si el objeto que se utiliza temporalmente, ese tiempo utiliza el contexto de la aplicación y el contexto de la actividad se utiliza totalmente opuesto al contexto de la aplicación.