Pregunta Dialog throwing "No se puede agregar la ventana - token null no es para una aplicación" con getApplication () como contexto


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, estoy receloso 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. A partir de una publicación relacionada en el blog del desarrollador de Android:

Hay dos formas sencillas de evitar fugas de memoria relacionadas con el contexto. El más obvio 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 usar el contexto de la aplicación. Este contexto vivirá mientras su aplicación esté viva 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() ninguno getApplicationContext() o getApplication() es aceptable como contexto, ya que arroja la excepción:

"No se puede agregar la ventana - token null no es para una aplicación"

por referencias: 1, 2, 3, etc.

Por lo tanto, si esto realmente se considera un "error", ya que se nos aconseja oficialmente que usemos Activity.getApplication() y sin embargo, ¿no funciona como se anuncia?

Jim


583
2018-04-26 21:21


origen


Respuestas:


En lugar de getApplicationContext(), Solo usa ActivityName.this.


1208
2017-08-29 11:04



Utilizando this no funcionó para mí, pero MyActivityName.this hizo. Espero que esto ayude a cualquiera que no pueda obtener this trabajar.


162
2018-06-21 00:54



Puedes continuar usando getApplicationContext(), pero antes de usar, debes agregar esta bandera: dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT)y el error no se mostrará

Agregue el siguiente permiso a su manifiesto:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

51
2017-12-25 08:09



No puedes mostrar una aplicación window/dialog a través de un Contexto eso no es un Actividad o servicio. Intenta pasar un referencia de actividad válida


33
2017-07-09 11:56



Su diálogo no debe ser un "objeto de larga duración que necesita un contexto". La documentación es confusa Básicamente si haces algo como:

static Dialog sDialog;

(nota la estático)

Luego, en una actividad en algún lugar que hiciste

 sDialog = new Dialog(this);

Probablemente estarías filtrando la actividad original durante una rotación o similar que destruiría la actividad. (A menos que limpie en Destroy, pero en ese caso probablemente no convierta el objeto Dialog 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:

Dialog mDialog;

...

mDialog = new Dialog(this);

Está bien y no debe filtrar la actividad ya que mDialog se liberaría con la actividad ya que no es estática.


30
2018-06-26 07:56



Identificó correctamente el problema cuando dijo "... para AlertDialog () ni getApplicationContext () ni getApplication () es aceptable como un contexto, ya que arroja la excepción: 'No se puede agregar la ventana - token null no es para Una aplicación'"

Para crear un cuadro de diálogo, necesita una Contexto de la actividad o una Contexto del servicio, no un Contexto de la aplicación (tanto getApplicationContext () como getApplication () devuelven un contexto de aplicación).

Así es como obtienes el Contexto de la 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());

Las pérdidas de memoria no son un problema que es intrínseco a la referencia "this", que es una referencia de un objeto a sí misma (es decir, referencia a la memoria asignada real para almacenar los datos del objeto). Pasa a alguna Memoria asignada para la cual el Garbage Collector (GC) no puede liberarse después de que la memoria asignada haya sobrevivido a su vida útil.

La mayoría de las veces, cuando una variable se sale del alcance, la memoria será recuperada por el GC. Sin embargo, las pérdidas de memoria pueden ocurrir cuando la referencia a un objeto sostenido por una variable, digamos "x", persiste incluso después de que el objeto ha sobrevivido a su vida útil. Por lo tanto, la memoria asignada se perderá mientras "x" contenga una referencia porque GC no lo hará liberar la memoria mientras se haga referencia a esa memoria. 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 fugas de memoria, verifique su código en busca de errores lógicos que causen que la memoria asignada sea referenciada indefinidamente por "this" (u otras referencias). Recuerde verificar también las referencias de la cadena. Aquí hay algunas herramientas que puede usar para ayudarlo a analizar el uso de la memoria y encontrar esas molestas pérdidas de memoria:


26
2017-10-07 23:37



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 los fragmentos ' onCreate llamar de vuelta.


22
2017-09-10 01:41



En Activity al hacer clic en el botón que muestra un cuadro de diálogo

Dialog dialog = new Dialog(MyActivity.this);

Trabajó para mi.


18
2018-02-27 11:26



Little hack: puedes evitar destruir la actividad mediante GC (por supuesto, no debes hacerlo, pero puede ayudarte en algunas situaciones):

public class PostActivity extends Activity  {
    ...
    private Context contextForDialog = null;
    ...
    public void onCreate(Bundle savedInstanceState) {
        ...
        contextForDialog = this;
    }
    ...
    private void showAnimatedDialog() {
        mSpinner = new Dialog(contextForDialog);
        mSpinner.setContentView(new MySpinner(contextForDialog));
        mSpinner.show();
    }
    ...
}

15
2017-12-03 10:03



Si está utilizando un fragmento y está utilizando el mensaje AlertDialog / Toast, use getActivity () en el parámetro de contexto.

Me gusta esto

ProgressDialog pdialog;
pdialog = new ProgressDialog(getActivity());
pdialog.setCancelable(true);
pdialog.setMessage("Loading ....");
pdialog.show();

12
2017-11-23 15:43