2010-11-19 10 views
6

Tengo una aplicación que puede mostrar y cerrar varios diálogos con:Android RuntimeException onCreateDialog no creó un cuadro de diálogo para la Identificación

showDialog(...) 
removeDialog(...) 

que jugar un poco con la aplicación y cuando no hay ningún diálogo en la pantalla, presiono el botón de menú y voy a la pantalla principal de Android.

Después de un tiempo, entro de nuevo en mi aplicación y, a veces, me sale este RuntimeException:

java.lang.IllegalArgumentException: Activity#onCreateDialog did not create a dialog for id 4 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2596) 
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2621) 
    at android.app.ActivityThread.access$2200(ActivityThread.java:126) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1932) 
    at android.os.Handler.dispatchMessage(Handler.java:99) 
    at android.os.Looper.loop(Looper.java:123) 
    at android.app.ActivityThread.main(ActivityThread.java:4595) 
    at java.lang.reflect.Method.invokeNative(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:521) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 
    at dalvik.system.NativeStart.main(Native Method) 
Caused by: java.lang.IllegalArgumentException: Activity#onCreateDialog did not create a dialog for id 4 
    at android.app.Activity.createDialog(Activity.java:878) 
    at android.app.Activity.restoreManagedDialogs(Activity.java:867) 
    at android.app.Activity.performRestoreInstanceState(Activity.java:815) 
    at android.app.Instrumentation.callActivityOnRestoreInstanceState(Instrumentation.java:1096) 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2565) 
    ... 11 more 

Alguna idea?

Muchas gracias.

UPDATE más información:

La aplicación onCreateDialog actual es:

protected Dialog onCreateDialog(int id){ 
Builder b = new AlertDialog.Builder(this); 
if(id == 4){ 
    b.setMessage(...); 
    b.setItems(items, new DialogInterface.OnClickListener(){ 
    public void onClick(DialogInterface dialog, int which){ 
    Intent i = new Intent(Current.this, Another.class); 
    startActivity(i); 
    } 
    }); 
    return b.create(); 
} 
return null; 
} 

Con el fin de llamar a esta función que hacer:

removeDialog(4); 
showDialog(4); 

Respuesta

2

Después de experimentar este mismo problema (y encontrar que llamar a removeDialog desde no funciona de manera confiable), desarrollé una solución que parece funcionar (aunque es cierto que es un truco).

Como se ve en la grepcode link posted by antslava, en el método performRestoreInstanceState, onRestoreInstanceState se llama justo antes de restoreManagedDialogs y se hace pasar la misma instancia de Bundle savedInstanceState.

final void performRestoreInstanceState(Bundle savedInstanceState) { 
    onRestoreInstanceState(savedInstanceState); 
    restoreManagedDialogs(savedInstanceState); 
} 

Por lo tanto, no hay posibilidad de modificar el Bundle savedInstanceState que se pasa a restoreManagedDialogs desde dentro del método onRestoreInstanceState.

para evitar cualquier y todos los diálogos administrados de ser restaurado, se podría aplicar onRestoreInstanceState de la siguiente manera:

// This same variable is defined as private in the Activity class. I need 
// access to it, so I redefine it here. 
private static final String SAVED_DIALOGS_TAG = "android:savedDialogs"; 

@Override 
protected void onRestoreInstanceState(Bundle savedInstanceState) { 
    super.onRestoreInstanceState(savedInstanceState); 
    final Bundle b = savedInstanceState.getBundle(SAVED_DIALOGS_TAG); 
    if (null != b) { 
     savedInstanceState.remove(SAVED_DIALOGS_TAG); 
    } 
} 

Esto hace que el Bundle referenciado por la clave "android:savedDialogs" ser eliminado de Bundle savedInstanceState, que posteriormente se hace la llamada restoreManagedDialogs a regresar inmediatamente cuando se encuentra que esta clave no se puede encontrar:

private void restoreManagedDialogs(Bundle savedInstanceState) { 
    final Bundle b = savedInstanceState.getBundle(SAVED_DIALOGS_TAG); 
    if (b == null) { 
     return; 
    } 
    ... 
} 

esto hará que onCreateDialog para no ser llamado mientras se restaura la Actividad, efectivamente "ocultando" cualquier cuadro de diálogo, evitando así que ocurra el escenario en el que uno debe devolver null desde onCreateDialog.

No se trata de una solución de "talla única", pero teniendo en cuenta mis requisitos, parece ajustarse a la factura. Al revisar el código en grepcode para varias versiones de plataforma (1.6, 2.1, 2.2, 2.2.2 y 4.0.3), parece que esta solución debería funcionar de manera consistente dadas estas implementaciones existentes.

0

se han ejecutado OnCreateDialog tal como se presenta here? Cuando llame a showDialog (4) por primera vez, se llamará a OnCreateDialog (4) y tendrá que crear el diálogo y devolverlo desde este método.

+0

Sí, todo el código funciona perfectamente bien. La aplicación no falla en ningún lado. Actualmente veo los diálogos apareciendo y cerrando perfectamente. El problema comienza aleatoriamente cuando reinicio la aplicación. – zegnus

0

¿Está devolviendo correctamente el cuadro de diálogo en onCreateDialog? Si tuviera que hacer dialog.show() en el diálogo crear pero devolver algún otro cuadro de diálogo, tal vez podría obtener un resultado como ese.

O haces cualquier tipo de manipulación en el objeto de diálogo en el onPrepareDialog

+0

Sí, el diálogo se crea bien con Builder b = new AlertDialog.Builder (this); ...; return b.create(); Cada vez que muestro el diálogo, llamo removeDialog (4) y luego showDialog (4) porque el contenido del diálogo cambia. No anulo onPrepareDialog ... – zegnus

11

En el nivel API 8, onCreateDialog(int) fue deprecated a favor de onCreateDialog(int,Bundle). Si implementa solo el último método y ejecuta la aplicación en un dispositivo con un nivel de API inferior a 8, obtendrá el mensaje de error descrito.

La solución es implementar onCreateDialog(int)

+0

Hola, mi objetivo actual es 8 pero mi minversion es 3. He actualizado la publicación con mi implementación onCreateDialog (int). ¡Gracias! – zegnus

4

Para SDK versión < 8, si vuelve nulo en onCreateDialog se obtiene java.lang.IllegalArgumentException Excepción.

+0

Genial, podría ser eso. Dentro de mi cuadro de diálogo número 4, tuve una verificación interna y, si falla, devolverá nulo. Yo que este podría ser el error. Aunque en la documentación oficial, existe la opción de devolver nulo http://developer.android.com/guide/topics/ui/dialogs.html pero creo que el problema es que anteriormente, la aplicación podía mostrar el diálogo , luego el usuario va a otra aplicación, y cuando regresa, la aplicación intenta restaurar el diálogo, pero esta vez devuelve nulo. Lo comprobaré, gracias! – zegnus

+1

Aquí puedes verlo http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.1_r2/android/app/Activity.java#Activity.createDialog%28java .lang.Integer% 2Candroid.os.Bundle% 29. Y para solucionarlo, necesita utilizar el método removeDialog, ya que este método elimina su diálogo de mManagedDialogs. – antslava

Cuestiones relacionadas