2012-08-24 13 views
42

Implementazione di un'app in cui l'utente può accedere Ho la seguente situazione: Se l'utente è connesso esegui l'azione altrimenti avvia l'attività di accesso per risultato e se il risultato è Activity.RESULT_OK fai l'azione.Azioni in onActivityResult e "Errore Impossibile eseguire questa azione dopo onSaveInstanceState"

mio problema è che l'azione da perfom è quello di mostrare un DialogFragment, ma chiamando

DialogFragment newFragment = MyDialogFragment.newInstance(mStackLevel); 
newFragment.show(ft, "dialog") 

nella richiamata onActivityResult genera un'eccezione:

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

Così come posso risolvere questo problema? Sto pensando a sollevare una bandiera lì e mostrare la finestra di dialogo nella onResume ma vedo questa soluzione un po 'sporco

Edit: Aggiunto più codice (Im seguendo questo esempio per mostrare il DialogFragment

Quando l'azione è richiesto dall'utente:

... 
if (!user.isLogged()){ 
startActivityForResult(new Intent(cnt, Login.class), REQUEST_LOGIN_FOR_COMMENT); 
} 

Nello stesso frammento

@Override 
public void onActivityResult(int requestCode, int resultCode, Intent data) { 
    super.onActivityResult(requestCode, resultCode, data); 
    if (requestCode == REQUEST_LOGIN_FOR_COMMENT && resultCode == Activity.RESULT_OK) { 
     FragmentTransaction ft = getFragmentManager().beginTransaction(); 
     DialogFragment newFragment = MyDialogFragment.newInstance(); 
     newFragment.show(ft, "dialog") 
    } 
} 

E se l'utente accede dell'attività Accesso chiamate;

setResult(Activity.RESULT_OK); 
finish(); 
+0

penso che dovresti postare l'intero codice. Sembra che tu stia cercando di mostrare il dialogo dopo la pausa – nandeesh

+0

Modificato la domanda: D – Addev

+1

Controlla http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html per capire perché questo sta accadendo – Maragues

risposta

94

La cosa migliore che mi è venuta in mente è non usare .show() ma piuttosto farlo.

CheckinSuccessDialog dialog = new CheckinSuccessDialog(); 
//dialog.show(getSupportFragmentManager(), null); 
FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); 
ft.add(dialog, null); 
ft.commitAllowingStateLoss(); 
+2

Anche se funziona per me, mi sento pericoloso perché abbiamo omesso 2 variabili: mDismissed = false; mShownByMe = true; Le variabili precedenti sono in corso di modifica nella funzione di visualizzazione originale. –

+2

grazie, commitAllowingStateLoss ha risolto il problema per me –

+0

mDismissed e mShowByMe sembrano essere variabili specifiche per tracciare se la finestra di dialogo è stata mostrata/nascosta da chiamate esterne. In altre parole, compensano esattamente questo tipo di cose. –

9

Ecco la soluzione che funziona correttamente per me.

private void alert(final String message) { 
    Handler handler = new Handler(Looper.getMainLooper()); 
    handler.post(new Runnable() { 
     public void run() { 
      AlertDialogFragment alertDialogFragment = AlertDialogFragment.newInstance(message); 
      alertDialogFragment.show(getFragmentManager(), ALERT_DIALOG_FRAGMENT); 
     } 
    });   
} 
4

Se si utilizza un DialogFragment, l'unica cosa che ha funzionato per me è stato quello di respingere il Frammento con dissmissAllowingStateLoss()

3

ho semplicemente controllare se un'attività viene distrutta.

if (!getActivity().isFinishing()) { 
    DialogFragment fragment = MyFragment.newInstance(); 
    fragment.show(getActivity().getSupportFragmentManager(), MyFragment.TAG); 
} 
1

Override show(Fragment manager, String tag) funzione con permettendo stato perdere e cambiare mDismissed = false;mShownByMe = true; dalla funzione origibal per riflessione:

public class DialogParent extends DialogFragment { 

    @Override 
    public void show(FragmentManager manager, String tag) { 
     try { 
      Field mDismissed = DialogFragment.class.getDeclaredField("mDismissed"); 
      Field mShownByMe = DialogFragment.class.getDeclaredField("mShownByMe"); 
      mDismissed.setAccessible(true); 
      mShownByMe.setAccessible(true); 
      mDismissed.setBoolean(this, false); 
      mShownByMe.setBoolean(this, true); 
     } catch (NoSuchFieldException e) { 
      e.printStackTrace(); 
     } catch (IllegalAccessException e) { 
      e.printStackTrace(); 
     } 
     FragmentTransaction ft = manager.beginTransaction(); 
     ft.add(this, tag); 
     ft.commitAllowingStateLoss(); 
    } 
} 
+0

Puoi anche circondare il metodo show dei genitori con un try-catch, dove nel catch aggiungi la finestra di dialogo e usa la transazione chiamata 'commitAllowingStateLoss()'. In questo modo non hai bisogno di alcun riflesso. – SimonSimCity

0

Questo vere e proprie opere.

CheckinSuccessDialog dialog = new CheckinSuccessDialog(); 
//dialog.show(getSupportFragmentManager(), null); 
FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); 
ft.add(dialog, null); 
ft.commitAllowingStateLoss(); 

Ma, ma ancora male, perché ha ricevuto l'errore “di attività è stata distrutta”

ava.lang.IllegalStateException: Activity has been destroyed fragmentTransaction.commitAllowingStateLoss(); 

Quindi la mia soluzione è aggiungere controllare if (!isFinishing()&&!isDestroyed())

CheckinSuccessDialog fragment = CheckinSuccessDialog.newInstance(); 

    if (fragment instanceof DialogFragment) { 
       DialogFragment dialog = (DialogFragment) fragment; 
       if (!dialog.isAdded()) { 
        fragmentTransaction.add(dialog, 
          CheckinSuccessDialog.class.getName()); 
        if (!isFinishing()&&!isDestroyed()) { 
         fragmentTransaction.commitAllowingStateLoss(); 
        } 
       } 

on respingere:

FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); 
     Fragment fragment = getSupportFragmentManager().findFragmentByTag(CheckinSuccessDialog.class.getName()); 
     if (fragment != null && fragment instanceof DialogFragment) { 
      DialogFragment dialog = (DialogFragment) fragment; 
      dialog.dismiss(); 
      if (!isFinishing()&&!isDestroyed()) { 
       fragmentTransaction.commitAllowingStateLoss(); 
      } 
     } 
0

Questa eccezione è t si attiva ogni volta che un viene eseguito dopo che FragmentManager ha salvato il suo stato.Il modo semplice e pulito è verificare se lo stato FragmentManager ha già salvato prima di mostrare DialogFragment.

if(!getSupportFragmentManager.isStateSaved()) { 
    MyDialogFragment dialogFragment = new MyDialogFragment() 
    dialogFragment.show(getSupportFragmentManager, TAG); 
} 
Problemi correlati