82 votes

Afficher DialogFragment à partir de onActivityResult

J'ai le code suivant dans mon onActivityResult pour un fragment du mien:

 onActivityResult(int requestCode, int resultCode, Intent data){
   //other code
   ProgressFragment progFragment = new ProgressFragment();  
   progFragment.show(getActivity().getSupportFragmentManager(), PROG_DIALOG_TAG);
   // other code
}
 

Cependant, j'obtiens l'erreur suivante:

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

Quelqu'un sait ce qui se passe ou comment je peux résoudre ce problème? Je dois noter que j'utilise le Support Package Android.

76voto

Arcao Points 361

Si vous utilisez la bibliothèque de support Android, la méthode onResume n'est pas le bon endroit pour jouer avec des fragments. Vous devez le faire dans la méthode onResumeFragments, voir Description de la méthode onResume: http://developer.android.com/reference/android/support/v4/app/FragmentActivity.html#onResume%28%29

Donc, le code correct de mon point de vue devrait être:

 private boolean mShowDialog = false;

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
  // remember that dialog should be shown
  mShowDialog = true;
}

@Override
protected void onResumeFragments() {
  super.onResumeFragments();

  // play with fragments here
  if (mShowDialog) {
    mShowDialog = false;

    // Show only if is necessary, otherwise FragmentManager will take care
    if (getSupportFragmentManager().findFragmentByTag(PROG_DIALOG_TAG) == null) {
      new ProgressFragment().show(getSupportFragmentManager(), PROG_DIALOG_TAG);
    }
  }
}
 

27voto

Kurtis Nusbaum Points 16073

En fait c'est un bug connu avec le paquet de soutien. Une posté contourner dans les commentaires du rapport de bug est de modifier le code source de la DialogFragment comme suit:

public int show(FragmentTransaction transaction, String tag) {
    return show(transaction, tag, false);
}


public int show(FragmentTransaction transaction, String tag, boolean allowStateLoss) {
    transaction.add(this, tag);
    mRemoved = false;
    mBackStackId = allowStateLoss ? transaction.commitAllowingStateLoss() : transaction.commit();
    return mBackStackId;
}

Notons que c'est un géant hack. La façon dont je l'ai fait il suffit de faire ma propre boîte de dialogue fragment que j'ai pu enregistrer avec du fragment initial. Lorsque cette autre boîte de dialogue fragment a fait des choses (comme être rejeté), il a dit à tout les auditeurs qu'il s'en allait. J'ai fait comme ceci:

public static class PlayerPasswordFragment extends DialogFragment{

 Player toJoin;
 EditText passwordEdit;
 Button okButton;
 PlayerListFragment playerListFragment = null;

 public void onCreate(Bundle icicle){
   super.onCreate(icicle);
   toJoin = Player.unbundle(getArguments());
   Log.d(TAG, "Player id in PasswordFragment: " + toJoin.getId());
 }

 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle icicle){
     View v = inflater.inflate(R.layout.player_password, container, false);
     passwordEdit = (EditText)v.findViewById(R.id.player_password_edit);
     okButton = (Button)v.findViewById(R.id.ok_button);
     okButton.setOnClickListener(new View.OnClickListener(){
       public void onClick(View v){
         passwordEntered();
       }
     });
     getDialog().setTitle(R.string.password_required);
     return v;
 }

 public void passwordEntered(){
   //TODO handle if they didn't type anything in
   playerListFragment.joinPlayer(toJoin, passwordEdit.getText().toString());
   dismiss();
 }

 public void registerPasswordEnteredListener(PlayerListFragment playerListFragment){
   this.playerListFragment = playerListFragment;
 }

 public void unregisterPasswordEnteredListener(){
   this.playerListFragment = null;
 }
}

Alors maintenant, j'ai une façon d'avertir le PlayerListFragment où les choses se passent. Notez qu'il est très important que vous appelez unregisterPasswordEnteredListener de manière appropriée (dans le cas ci-dessus quand jamais le PlayerListFragment "s'en va"), sinon cette boîte de dialogue fragment pourrait essayer d'appeler des fonctions sur le régime enregistré d'écouteur lorsque que l'auditeur n'existe plus.

14voto

hrnt Points 5835

Android appelle onActivityResult() avant onStart() .

Je l'ai résolu en stockant essentiellement l'intention en tant que paramètre que j'ai ensuite traité dans onResume() .

11voto

Simon Jacobs Points 57

EDIT: Encore une autre option, et peut-être le meilleur encore (ou du moins ce que la bibliothèque de prise en charge s'attend...)

Si vous utilisez DialogFragments avec l'Android support library, vous devriez être en utilisant une sous-classe de FragmentActivity. Essayez les solutions suivantes:

onActivityResult(int requestCode, int resultCode, Intent data) {

   super.onActivityResult(requestCode, resultCode, intent);
   //other code

   ProgressFragment progFragment = new ProgressFragment();  
   progFragment.show(getActivity().getSupportFragmentManager(), PROG_DIALOG_TAG);

   // other code
}

J'ai pris un coup d'oeil à la source pour FragmentActivity, et il semble que c'est l'appel d'un fragment interne gestionnaire, afin de reprendre des fragments sans perdre état.


J'ai trouvé une solution qui n'est pas listée ici. J'ai créer un Gestionnaire, et de commencer le dialogue fragment dans le Gestionnaire. Ainsi, l'édition de votre code un peu:

onActivityResult(int requestCode, int resultCode, Intent data) {

   //other code

   final FragmentManager manager = getActivity().getSupportFragmentManager();
   Handler handler = new Handler();
   handler.post(new Runnable() {
       public void run() {
           ProgressFragment progFragment = new ProgressFragment();  
           progFragment.show(manager, PROG_DIALOG_TAG);
       }
   }); 

  // other code
}

Cela semble plus propre et moins hacky pour moi.

4voto

handrenliang Points 366

Vous ne pouvez pas afficher de dialogue après activité attachée appelée sa méthode onSaveInstanceState (). Évidemment, onSaveInstanceState () est appelé avant onActivityResult (). Donc, vous devriez montrer votre dialogue dans cette méthode de rappel OnResumeFragment (), vous n'avez pas besoin de remplacer la méthode show () de DialogFragment. J'espère que ceci vous aidera.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X