Mi actividad está intentando crear un AlertDialog que requiere un contexto como parámetro. Esto funciona como se esperaba si uso:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
Sin embargo, desconfío de usar "esto" como contexto debido a la posibilidad de pérdidas de memoria cuando la actividad se destruye y se recrea incluso durante algo simple como una rotación de pantalla. De una publicación relacionada en el blog del desarrollador de Android :
Hay dos maneras fáciles de evitar pérdidas de memoria relacionadas con el contexto. La más obvia es evitar escapar del contexto fuera de su propio alcance. El ejemplo anterior mostró el caso de una referencia estática, pero las clases internas y su referencia implícita a la clase externa pueden ser igualmente peligrosas. La segunda solución es utilizar el contexto de la aplicación. Este contexto vivirá mientras su aplicación esté activa y no dependa del ciclo de vida de las actividades. Si planea mantener objetos de larga duración que necesitan un contexto, recuerde el objeto de la aplicación. Puede obtenerlo fácilmente llamando a Context.getApplicationContext () o Activity.getApplication ().
Pero para el AlertDialog()
ningunogetApplicationContext()
o getApplication()
es aceptable como contexto, ya que arroja la excepción:
"No se puede agregar la ventana: el token nulo no es para una aplicación"
por referencias: 1 , 2 , 3 , etc.
Entonces, si esto realmente se considera un "error", ya que se nos recomienda oficialmente usar Activity.getApplication()
y, sin embargo, no funciona como se anuncia?
Jim
Respuestas:
En lugar de
getApplicationContext()
, solo úsaloActivityName.this
.fuente
Listener
clases suelen ser anónimas internas, tiendo a hacerlofinal Context ctx = this;
y estoy fuera;)Usar
this
no funcionó para mí, pero loMyActivityName.this
hizo. Espero que esto ayude a cualquiera que no pueda irthis
a trabajar.fuente
this
desde el interior de una clase interna. Si desea hacer referencia a la instancia de una clase externa, debe especificarlo, como lo hace conOuterClass.this
. Solo usandothis
siempre hace referencia a la instancia de la clase más interna.Puede continuar usándolo
getApplicationContext()
, pero antes de usarlo, debe agregar este indicador:dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT)
y el error no se mostrará.Agregue el siguiente permiso a su manifiesto:
fuente
Has identificado correctamente el problema cuando dijiste "... para AlertDialog () ni getApplicationContext () ni getApplication () son aceptables como contexto, ya que arroja la excepción: 'No se puede agregar la ventana: el token nulo no es para Una aplicación'"
Para crear un diálogo, necesita un contexto de actividad o un contexto de servicio , no un contexto de aplicación (getApplicationContext () y getApplication () devuelven un contexto de aplicación).
Así es como obtienes el contexto de actividad :
(1) En una actividad o un servicio:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
(2) En un fragmento:
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
La pérdida de memoria no es un problema intrínseco a la referencia "este", que es la referencia de un objeto a sí misma (es decir, la referencia a la memoria asignada real para almacenar los datos del objeto). Le sucede a cualquier memoria asignada para la cual el recolector de basura (GC) no puede liberarse después de que la memoria asignada haya sobrevivido su vida útil.
La mayoría de las veces, cuando una variable queda fuera de alcance, el GC recuperará la memoria. Sin embargo, pueden producirse pérdidas de memoria cuando la referencia a un objeto sostenido por una variable, digamos "x", persiste incluso después de que el objeto haya sobrevivido su vida útil. Por lo tanto, la memoria asignada se perderá mientras "x" tenga una referencia a ella porque el GC no liberará la memoria mientras esa memoria todavía esté siendo referenciada. A veces, las pérdidas de memoria no son evidentes debido a una cadena de referencias a la memoria asignada. En tal caso, el GC no liberará la memoria hasta que se hayan eliminado todas las referencias a esa memoria.
Para evitar pérdidas de memoria, revise su código en busca de errores lógicos que causen que la memoria asignada sea referenciada indefinidamente por "esto" (u otras referencias). Recuerde verificar las referencias de la cadena también. Estas son algunas herramientas que puede usar para ayudarlo a analizar el uso de memoria y encontrar esas molestas pérdidas de memoria:
JRockit Mission Control
JProbe
YourKit
AD4J
fuente
Su diálogo no debe ser un "objeto longevo que necesita un contexto". La documentación es confusa. Básicamente si haces algo como:
(tenga en cuenta la estática )
Luego, en una actividad en algún lugar que hiciste
Es probable que se filtre la actividad original durante una rotación o similar que destruiría la actividad. (A menos que limpie en onDestroy, pero en ese caso probablemente no haría que el objeto Dialog sea estático)
Para algunas estructuras de datos tendría sentido hacerlas estáticas y basadas en el contexto de la aplicación, pero generalmente no para cosas relacionadas con la interfaz de usuario, como los diálogos. Entonces algo como esto:
Está bien y no debería filtrar la actividad ya que mDialog se liberaría con la actividad ya que no es estática.
fuente
Tuve que enviar mi contexto a través de un constructor en un adaptador personalizado que se muestra en un fragmento y tuve este problema con getApplicationContext (). Lo resolví con:
this.getActivity().getWindow().getContext()
en laonCreate
devolución de llamada de los fragmentos .fuente
en Actividad solo use:
en Fragmento:
fuente
Al
Activity
hacer clic en el botón que muestra un cuadro de diálogoTrabajó para mi.
fuente
***** Kotlin versión *****
Debe pasar en
this@YourActivity
lugar deapplicationContext
obaseContext
fuente
Pequeño truco: se puede prevenir la destrucción de su actividad por GC (que no debería hacerlo, pero puede ayudar en algunas situaciones No se olvide de conjunto.
contextForDialog
Anull
cuando ya no es necesario):fuente
Si está utilizando un fragmento y está utilizando el mensaje AlertDialog / Toast, use getActivity () en el parámetro de contexto.
Me gusta esto
fuente
Solo use lo siguiente:
PARA USUARIOS DE JAVA
En caso de que estés usando actividad ->
AlertDialog.Builder builder = new AlertDialog.Builder(this);
O
AlertDialog.Builder builder = new AlertDialog.Builder(your_activity.this);
En caso de que estés usando un fragmento ->
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
PARA USUARIOS DE KOTLIN
En caso de que estés usando actividad ->
val builder = AlertDialog.Builder(this)
O
val builder = AlertDialog.Builder(this@your_activity.this)
En caso de que estés usando un fragmento ->
val builder = AlertDialog.Builder(activity!!)
fuente
agregando
y
"android.permission.SYSTEM_ALERT_WINDOW"/>
en manifiestoFunciona para mi ahora. Incluso después de cerrar y abrir la aplicación, me dio el error en ese momento.
fuente
Estaba usando
ProgressDialog
un fragmento y obtenía este error al pasargetActivity().getApplicationContext()
como el parámetro constructor. Cambiarlo agetActivity().getBaseContext()
tampoco funcionó.La solución que funcionó para mí fue pasar
getActivity()
; es decirprogressDialog = new ProgressDialog(getActivity());
fuente
Utilizar
MyDialog md = new MyDialog(MyActivity.this.getParent());
fuente
Si está fuera de la Actividad, entonces debe usar en su función "NameOfMyActivity.this" como actividad de la Actividad, por ejemplo:
fuente
Si está utilizando un fragmento y un
AlertDialog / Toast
mensaje, utilícelogetActivity()
en el parámetro de contexto.Trabajó para mi.
¡Salud!
fuente
Intente utilizar el contexto de una actividad que estará debajo del diálogo. Pero tenga cuidado cuando use "esta" palabra clave, porque no funcionará todo el tiempo.
Por ejemplo, si tiene TabActivity como host con dos pestañas, y cada pestaña es otra actividad, y si intenta crear un diálogo desde una de las pestañas (actividades) y si usa "this", obtendrá una excepción. el cuadro de diálogo de caso debe estar conectado a la actividad del host que aloja todo y visible. (puede decir el contexto de actividad principal más visible)
No encontré esta información en ningún documento sino al intentarlo. Esta es mi solución sin antecedentes sólidos. Si alguien con mejor conocimiento, no dude en comentar.
fuente
Para futuros lectores, esto debería ayudar:
fuente
En mi caso trabajo:
fuente
O otra posibilidad es crear el diálogo de la siguiente manera:
fuente
Creo que también puede suceder si está intentando mostrar un diálogo desde un hilo que no es el hilo principal de la interfaz de usuario.
Usar
runOnUiThread()
en ese caso.fuente
Intente
getParent()
en el lugar del contexto del argumento como nuevoAlertDialog.Builder(getParent());
Espero que funcione, funcionó para mí.fuente
Después de echar un vistazo a la API, puede pasar el diálogo a su actividad o getActivity si está en un fragmento, luego limpiarlo con fuerza con dialog.dismiss () en los métodos de retorno para evitar fugas.
Aunque no se menciona explícitamente en ningún lugar que conozca, parece que le devolvió el cuadro de diálogo en OnClickHandlers solo para hacer esto.
fuente
Si su diálogo se está creando en el adaptador:
Pase la actividad al constructor del adaptador:
Recibir en el adaptador:
Ahora puedes usarlo en tu Builder
fuente
Así es como resolví el mismo error para mi aplicación:
Agregar la siguiente línea después de crear el diálogo:
No necesitará adquirir un contexto. Esto es particularmente útil si está apareciendo otro cuadro de diálogo sobre el cuadro de diálogo emergente actual. O cuando no es conveniente obtener un contexto.
Espero que esto pueda ayudarte con el desarrollo de tu aplicación.
David
fuente
fuente