¿Por qué AlertDialog.Builder (Context context) sólo acepta Actividad como parámetro?

En mi proceso de aprendizaje en curso (cuadros de diálogo esta vez), descubrí que esto funciona:

AlertDialog.Builder builder = new AlertDialog.Builder(this); 

Mientras que lo siguiente no funciona (falla en tiempo de ejecución con WindowManager $ BadTokenException):

  AlertDialog.Builder builder = new AlertDialog.Builder(this.getApplicationContext()); 

No entiendo por qué, porque el constructor de AlertDialog.Builder está definido para aceptar Contexto como un parámetro, no Actividad:

Public AlertDialog.Builder (Contexto contextual)

Constructor utilizando un contexto para este constructor y el AlertDialog que crea.

¿Qué me estoy perdiendo?

Una actividad hereda un contexto. AlertDialog.Builder especifica un argumento de Contexto porque puede ser utilizado por CUALQUIER clase que sea una subclase de Contexto, incluyendo una Actividad, ListActivity, Service, … (Hay un lenguaje de codificación común detrás de esto – puedes aprender más sobre él Leyendo el ítem I8 (sobre clases de Interfaces y Abstracts) en el fantástico Java Efectivo de Joshua Bloch).

GetApplicationContext () devuelve el contexto de su aplicación, que es mayormente el mismo que su contexto de actividades – y el "principalmente" es lo que te está tirando. Los detalles no son claros, pero este es un problema ampliamente encontrado, y la respuesta típica es utilizar el contexto que va a escribir la alerta a la pantalla. Tenga en cuenta que no es el que devuelve getApplicationContext ().

Ahora si eres como yo, puedes decir "pero estoy trabajando en una clase que no hereda de Actividad – por lo que quiero usar getApplicationContext () para esto en primer lugar – duh!" En realidad, no hablo tan groseramente como eso, p .. el punto era que he estado aquí también. Lo arreglé así: 1) pregúntese "¿tengo mi código UI AlertDialog en una clase que no sea de actividad porque quiero compartirla entre actividades .. o incluso a través de ListActivities, Services, …?". Si no, hmmm … ¿realmente tiene AlertDialog UI llamadas en código que no puede garantizar tendrá acceso a la interfaz de usuario (y, por tanto, contexto)? Si es así, reconsidere su diseño.

Suponiendo que desea compartir esta clase a través de Actividades, … la respuesta queda clara. Desea que su clase sea utilizable por una variedad de personas que llaman, cada una probablemente con su propio contexto: por lo que la persona que llama debe pasar su contexto a su clase como un argumento:

myClass(Context theContext, ...) { ... }

Cada actividad, servicio, etc. hace llamadas así:

myClass(this, ...);

¿Parecer familiar?

Ten cuidado! Que si está compartiendo código, debe considerar la posibilidad de que diferentes llamadas entren en su código compartido en paralelo, con todas las muchas ramificaciones. Eso está más allá de nuestro alcance aquí …

Que te diviertas 🙂

AlertDialog es una subclase de Dialog , que tiene una ventana asociada, que tiene un LayoutParams asociado. Uno de esos parámetros es el tipo de ventana. El tipo predeterminado es TYPE_APPLICATION_ATTACHED_DIALOG , que requiere una ventana primaria.

El WindowManager asociado a una Actividad está configurado para utilizar la ventana de la Actividad como ventana principal. WindowManager asociado a una aplicación no tiene ninguna ventana asociada.

Bottom line: Para mostrar correctamente un cuadro de diálogo, tiene que cambiar el tipo de ventana predeterminado a un tipo que no requiere una ventana primaria o utilizar un contexto que tenga una ventana asociada.

  • Fugas de contexto de Android en AsyncTask
  • ¿Forma estática de obtener 'Contexto' en Android?
  • Cómo extender LinearLayout correctamente para crear una vista personalizada
  • obtiene el objeto Activity mientras está en el contexto View
  • OnBind () en servicio siempre devuelve Falso - Android
  • Obtener el contexto en una clase que implementa Runnable
  • ¿Tengo fugas de contexto?
  • Cómo obtener el contexto de BaseAdapter en Android
  • Obtenga correo electrónico, ID y teléfono de contacto (no utiliza actividad)
  • Por favor, explícame Clase de contexto en Android
  • Android: Inicie el servicio con Context.startService vs PendingIntent.getService
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.