2012-01-30 19 views
14

Sí, he leído las innumerables preguntas sobre el mismo problema de.Actividad se ha filtrado ventana/diálogo (¡esto otra vez!)

Mi código es simple: simplemente uso showDialog(int id) en el onCreate, y luego giro el dispositivo. El código es solo eso (caso de prueba), y eso es suficiente para causar el problema. Tenía entendido que los métodos de showDialog se encargarían de eso ... el diálogo desaparecería y luego se llamaría al onCreate más tarde después del cambio y se mostraría el diálogo de nuevo, limpiamente. Pero no. ¿Qué hay de malo en este razonamiento?

Yo (creo) entiendo the cause, pero no sé cómo resolver eso. Incluso la aplicación iosched tiene el mismo problema con su implementación de la ventana EULA (cambie la orientación en el diálogo eula y obtendrá la fuga). He leído sobre descartar el diálogo en OnPause, pero 1) Me arriesgo a descartarlo cuando aún no se muestra, y 2) el seguimiento del diálogo parece demasiado trabajo. Debe haber un enfoque más robusto.

Entonces ... ¿cuál es el código más limpio que se necesita para manejar eso?

Gracias.


de registro de salida de error:

01-30 00:27:18.615: E/WindowManager(20316): Activity com.test.PreSetupActivity has leaked window [email protected] that was originally added here 
01-30 00:27:18.615: E/WindowManager(20316): android.view.WindowLeaked: Activity com.test.PreSetupActivity has leaked window [email protected] that was originally added here 
01-30 00:27:18.615: E/WindowManager(20316):  at android.view.ViewRootImpl.<init>(ViewRootImpl.java:343) 
01-30 00:27:18.615: E/WindowManager(20316):  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:245) 
01-30 00:27:18.615: E/WindowManager(20316):  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:193) 
01-30 00:27:18.615: E/WindowManager(20316):  at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:118) 
01-30 00:27:18.615: E/WindowManager(20316):  at android.view.Window$LocalWindowManager.addView(Window.java:537) 
01-30 00:27:18.615: E/WindowManager(20316):  at android.app.Dialog.show(Dialog.java:274) 
01-30 00:27:18.615: E/WindowManager(20316):  at com.test.PreSetupActivity.onCreate(PreSetupActivity.java:88) 
01-30 00:27:18.615: E/WindowManager(20316):  at android.app.Activity.performCreate(Activity.java:4465) 
01-30 00:27:18.615: E/WindowManager(20316):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049) 
01-30 00:27:18.615: E/WindowManager(20316):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1919) 
01-30 00:27:18.615: E/WindowManager(20316):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1980) 
01-30 00:27:18.615: E/WindowManager(20316):  at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3347) 
01-30 00:27:18.615: E/WindowManager(20316):  at android.app.ActivityThread.access$700(ActivityThread.java:122) 
01-30 00:27:18.615: E/WindowManager(20316):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1150) 
01-30 00:27:18.615: E/WindowManager(20316):  at android.os.Handler.dispatchMessage(Handler.java:99) 
01-30 00:27:18.615: E/WindowManager(20316):  at android.os.Looper.loop(Looper.java:137) 
01-30 00:27:18.615: E/WindowManager(20316):  at android.app.ActivityThread.main(ActivityThread.java:4340) 
01-30 00:27:18.615: E/WindowManager(20316):  at java.lang.reflect.Method.invokeNative(Native Method) 
01-30 00:27:18.615: E/WindowManager(20316):  at java.lang.reflect.Method.invoke(Method.java:511) 
01-30 00:27:18.615: E/WindowManager(20316):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) 
01-30 00:27:18.615: E/WindowManager(20316):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) 
01-30 00:27:18.615: E/WindowManager(20316):  at dalvik.system.NativeStart.main(Native Method) 
+0

veo algunas personas están manteniendo un registro de las ventanas, básicamente la creación de ellos sin el método 'showDialog', y comprobando si se muestran (' isShowing() '), y luego descartando en consecuencia (en onStop/onPause). Sin embargo, creo que es una buena idea decir que la forma automática (showDialog) debería ser más limpia y fácil, ¿no? – davidcesarino

+0

puede cerrar el diálogo en onPostexecute(), como dialog.dismiss(); – user3114805

+0

Me gustaría ir con DialogFragment en su lugar. Gestiona la rotación de forma automática y, por lo tanto, es más elegante. – WindRider

Respuesta

13

Tener una clase interna que actúa como su stateholder y tienen un campo booleano ahí que indica si o no su diálogo está mostrando. Realizar un seguimiento de esto a través de la orientación usando sólo cambia onRetainNonConfigurationInstance y simplemente volver a mostrar el cuadro de diálogo de onResume

Aquí hay un código + pseudo-código:

public class ProfileActivity extends Activity { 
    private StateHolder mStateHolder; 
    private Dialog dialog; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    Object retained = getLastNonConfigurationInstance(); 
    if (retained != null && retained instanceof StateHolder) { 
     mStateHolder = (StateHolder) retained; 
    } else { 
     mStateHolder = new StateHolder(); 
    } 
    } 

    @Override 
    public Object onRetainNonConfigurationInstance() { 
    return mStateHolder; 
    } 

    @Override 
    public void onPause() { 
    super.onPause(); 
    if(dialog != null && dialog.isShowing()) { 
     dialog.dismiss(); 
    } 
    } 

    @Override 
    public void onResume() { 
    if(mStateHolder.mIsShowingDialog) { 
     dialog.show(); 
    } 
    } 

    private void showDialog() { 
    mStateHolder.mIsShowingDialog = true; 
    dialog.show(); 
    } 

    private static class StateHolder { 
    boolean mIsShowingDialog; 
    public StateHolder() {} 
    } 

} 
+0

Hmmm, desafortunadamente me estoy convenciendo de que 'showDialog' es solo un PITA (lo siento). Probaré esta solución con respecto a los diálogos manuales e informaré de nuevo. ¡Gracias! – davidcesarino

+1

Gracias de nuevo. ¡Estoy usando el concepto anterior y está funcionando perfectamente! Incluso presioné repetidamente Ctrl + F11 muy rápido en el emulador, cambiando la orientación alrededor de dos veces por segundo, muchas veces ... algo que un usuario en un teléfono normal nunca haría. Y mis líneas de registro estaban tan limpias como podría ser. Muchas gracias ya que esto me hizo perder bastante tiempo ayer. – davidcesarino

+0

Gran respuesta, utilicé 'onPause()' – rahstame

Cuestiones relacionadas