53

Empecé a usar DialogFragment, porque funcionan muy bien mediante cambios de orientación y cosas así. Pero hay un desagradable problema que encontré.Forma correcta de descartar DialogFragment mientras la aplicación está en segundo plano

Tengo AsyncTask que muestra el progreso DialogFragment y lo descarta onPostExecute. Todo funciona bien, excepto cuando ocurre onPostExecute mientras la aplicación está en segundo plano (después de presionar el botón Inicio, por ejemplo). Luego obtuve este error en DialogFragment descartando - "Can not perform this action after onSaveInstanceState". Doh. Los diálogos regulares funcionan bien. Pero no FragmentDialog.

Así que me pregunto, ¿cuál es la forma correcta de descartar DialogFragment mientras la aplicación está en segundo plano? Realmente no he trabajado mucho con Fragments, así que creo que me estoy perdiendo algo.

+0

ver también [aquí] (http://stackoverflow.com/questions/7992496/how-to-handle-asynctask-onpostexecute-when-paused-to-avoid-illegalstateexception) para la solución utilizando una agradable pausa controlador – PJL

Respuesta

108

DialogFragment tiene un método llamado dismissAllowingStateLoss()

+7

Esto solo funciona si usa: ['show (FragmentManager, tag)'] (http://developer.android.com/reference/android/app/DialogFragment.html#show (android.app.FragmentManager,% 20java .lang.String)), pero no cuando se usa ['show (FragmentTransaction, tag)'] (http://developer.android.com/reference/android/app/DialogFragment.html#show (android.app.FragmentTransaction,% 20java.lang.String)) porque 'popBackStack' en' dismissInternal' llama 'enqueueAction (..., allowStateLoss = false)' aunque pedimos que se permitiera la pérdida del estado. Y lo hace tanto en el marco como en las versiones de soporte. – TWiStErRob

+0

http://stackoverflow.com/a/10261449/1815624 – CrandellWS

0

Una solución que podría funcionar es establecer Fragment.setRetainInstance(true) en su fragmento de diálogo, pero esa no es la solución más bonita.

A veces he notado que tengo que poner en cola mis acciones de diálogo para permitir que la estructura restablezca el estado primero. Si puede obtener el Looper actual (Activity.getMainLooper()) y ajustarlo en un Manejador, puede intentar pasar su despido al final de la cola publicando un ejecutable en esa cola.

A menudo termino usando un fragmento separado que es retaininstance(true) que tiene un ResultReceiver. Así que transfiero ese receptor de resultados a mis trabajos y manejo las devoluciones de llamada en su recepción (a menudo como enrutador para otros receptores). Pero eso podría ser un poco más trabajo de lo que vale si está utilizando tareas asíncronas.

8

Esto es lo que hice (df == dialogFragment):

Asegúrese de que usted llama el diálogo de esta manera:

df.show(getFragmentManager(),"DialogFragment_FLAG"); 

Cuando desee dismis la composición de diálogo este control:

if(df.isResumed()){ 
    df.dismiss(); 
} 
return; 

Asegúrese de que tiene el siguiente en el método onResume() de su fragmento (no df)

@Override 
public void onResume(){ 
    Fragment f= getFragmentManager().findFragmentByTag("DialogFragment_FLAG"); 
    if (f!= null) { 
    DialogFragment df = (DialogFragment) f; 
    df.dismiss(); 
    getFragmentManager().beginTransaction().remove(f).commit(); 
    } 
    super.onResume(); 
} 

De esta manera, se desestimó el cuadro de diálogo si es visible .. si no es visible el cuadro de diálogo va a ser dismisded siguiente fragmento se hace visible (onResume) ...

+0

Esto siempre descarta el fragmento cuando el usuario regresa, ¿qué pasa si aún no leyeron el diálogo, simplemente abandonaron la aplicación justo después de que se muestra? – TWiStErRob

+0

ahora puedo rechazar el fragmento de diálogo por este código –

3

Esto es lo que tenía que hacer para lograr lo que quiere: que tienen una actividad de fragmento en el que estaba mostrando un fragmento de diálogo llamado fragment_RedemptionPayment que se declara a nivel mundial a la parte superior. El siguiente código descarta el DialogFragment si se muestra antes de que la actividad entre en segundo plano y regrese al primer plano.

 @Override 
     public void onResume() { 
      super.onResume();   
      if(fragment_RedemptionPayment.isVisible()){ 
       fragment_RedemptionPayment.dismiss(); 
      } 
} 
Cuestiones relacionadas