6

Ciao Sto sviluppando un'applicazione che utilizza le mappe.Il frammento della finestra di dialogo respinto riappare di nuovo quando viene ripristinata l'app

Sto utilizzando Fragment Activity e un frammento denominato Fragment-A.

In Fragment-A c'è un pulsante, facendo clic su quel pulsante si apre un frammento della finestra di dialogo, viene visualizzata una mappa con una posizione ricevuta in precedenza dal server.

Diciamo che questo frammento di finestra di dialogo è DialogFragment-B.

Ha un pulsante per chiudere, un pulsante per navigare verso l'app google maps per ottenere indicazioni stradali.

Se l'utente passa a DialogFragment-B e torna al frammento-A, facendo clic sul pulsante di chiusura, ogni cosa funziona correttamente.

Ma se l'utente fa clic sul pulsante Indietro, il frammento di finestra di dialogo esistente verrà chiuso normalmente e l'app funzionerà normalmente.

Ma se l'utente poi preme il pulsante di casa o ha ricevuto una telefonata e onResume è chiamata anche se il DialogFragment-B è respinto in precedenza, riappare e stringendosi si blocca l'applicazione con un'eccezione di puntatore nullo

Ecco il mio codice per aprire DialogFragment-B.

FragmentManager fm = getFragmentManager(); 
    FragmentTransaction ft = fm.beginTransaction(); 
    android.app.Fragment prev = fm.findFragmentByTag(MY_MAP); 
    if (prev != null) { 
     ft.remove(prev); 
    } 
    MyMapFragmentDialog newFragment = MyMapFragmentDialog 
      .newInstance(eachPost); 
    newFragment.show(ft, MY_MAP); 

In DialogFragment-B sul clic pulsante di chiusura, che io chiamo MyMapFragmentDialog.this.dismiss();

Per favore, se qualcuno ha riscontrato questo problema e ha superato, guidami attraverso.

+0

Penso che stai trascurando la transazione: 'ft.remove (prev). Com()' o aggiungi un'altra riga come 'ft.commit();' –

+0

Prova il 'MyMapFragmentDialog' all'interno del ciclo if. Il 'prev' diventa nullo e tu aggiungendo il frammento ad esso – GoCrazy

risposta

2

Aggiornamento: la risposta di Kalina è una soluzione più elegante e semplice - come ho capito dopo!

Sto affrontando lo stesso problema in una delle mie applicazioni, e non trovare la risposta da nessuna parte, ha attraversato il codice sorgente della classe DialogFragment, di cui dispone:

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.1_r1/android/app/DialogFragment.java#DialogFragment.onDismiss%28android.content.DialogInterface%29

e là , ho trovato il probabile motivo scritto in un commento, entro la fonte di onDismiss (finestra DialogInterface) metodo:

// Note: we need to use allowStateLoss, because the dialog 
// dispatches this asynchronously so we can receive the call 
// after the activity is paused. Worst case, when the user comes 
// back to the activity they see the dialog again. 

quello che ho capito da questo è che il licenziamento è non salvato nello stato dell'istanza e quando l'attività riprende, lo mostra prontamente come parte del ripristino dello stato dell'istanza, assumendo che il frammento non sia mai stato eliminato. Essendo un evento asincrono, non esiste un modo sicuro per commettere il respingere senza rischiare un'eccezione

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState 

e crash conseguente, che è probabilmente il motivo della classe gli autori hanno scelto di farlo in questo modo.

La soluzione che ha funzionato per me è stato quello di monitorare separatamente lo stato della DialogFragment, da:

  • riporlo in una variabile di classe (di cui qui come 'finestra')
  • Override del onDismiss (finestra DialogInterface) metodo e
  • impostazione di un flag dialogDismissed booleano true

-

@Override 
public void onDismiss(DialogInterface dialog) { 
    // dialogDismissed is a Class level variable in the containing Activity, 
    // must be set to false each time the DialogFragment is shown 
    dialogDismissed = true; 
} 
  • Nota: se il DialogFragment è una classe separata, quindi poi un metodo nella attività dovrà essere chiamato dal onDismiss per fare questo, forse, attraverso la creazione di un'interfaccia

  • Questo flag deve essere controllata attraverso l'attività onResume() e un respingere forzata (dopo aver verificato che la finestra non è nullo):

-

@Override 
public void onResume() { 
super.onResume(); 
//... 
if (dialogDismissed && dialog != null) { 
     dialog.dismiss(); 
    }  
} 
10

Ho avuto lo stesso problema ed è stato risolto facendo in modo che io chiamo super.onDismiss(dialog) nel metodo della mia DialogFragment sottoclasse onDismiss.

+0

Ho avuto lo stesso problema, questo ha risolto il mio. – qtyq

Problemi correlati