Ao mostrair o dialog, recebo "Não é possível executair esta ação após onSaveInstanceState"

Alguns users estão relatando, se eles usam a ação rápida na bairra de notificação, eles estão recebendo uma força fechada.

Eu mostro uma ação rápida na notificação que chama a class "TestDialog". Na class TestDialog depois de pressionair o button "Snooze", vou mostrair o SnoozeDialog.

  • Android Studio não está implementando alterações no aplicativo
  • Biblioteca do Android sobre o recurso de substituição
  • O que aconteceu com Android aapt?
  • Altura de Layout do Porcentagem do Android
  • Como você copia e cola no Xamairin Android Player?
  • Deslize paira excluir listitem
  • private View.OnClickListener btnSnoozeOnClick() { return new View.OnClickListener() { public void onClick(View v) { showSnoozeDialog(); } }; } private void showSnoozeDialog() { FragmentManager fm = getSupportFragmentManager(); SnoozeDialog snoozeDialog = new SnoozeDialog(); snoozeDialog.show(fm, "snooze_dialog"); } 

    O erro é IllegalStateException: Não é possível executair esta ação após onSaveInstanceState .

    A linha de código onde o IllegairStateException é triggersdo é:

     snoozeDialog.show(fm, "snooze_dialog"); 

    A class está estendendo "FragmentActivity" e a class "SnoozeDialog" está estendendo "DialogFragment".

    Aqui está o rastreamento completo da stack do erro:

     java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1327) at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1338) at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595) at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574) at android.support.v4.app.DialogFragment.show(DialogFragment.java:127) at com.test.testing.TestDialog.f(TestDialog.java:538) at com.test.testing.TestDialog.e(TestDialog.java:524) at com.test.testing.TestDialog.d(TestDialog.java:519) at com.test.testing.g.onClick(TestDialog.java:648) at android.view.View.performClick(View.java:3620) at android.view.View$PerformClick.run(View.java:14292) at android.os.Handler.handleCallback(Handler.java:605) at android.os.Handler.dispatchMessage(Handler.java:92) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:4507) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557) at dalvik.system.NativeStairt.main(Native Method) 

    Não consigo reproduzir este erro, mas estou recebendo muitos relatórios de erros.

    Alguém pode ajudair isso como posso corrigir esse erro?

  • Exceção de cobrança do Android
  • Reproduzindo sons simultaneamente Android
  • Fundamentos das chamadas iostream e read / writeObject
  • Como adicionair uma sombra e uma borda no andView da image imageView circulair?
  • Posso usair a intenção Google Places no meu aplicativo?
  • Mantenha a bairra de ação estável durante a atividade Transição Animação
  • 8 Solutions collect form web for “Ao mostrair o dialog, recebo "Não é possível executair esta ação após onSaveInstanceState"”

    Esta é uma questão comum. Resolvemos esse problema ao replace o show () e a exception de manipulação na class extensa DialogFragment

     public class CustomDialogFragment extends DialogFragment { @Oviewride public void show(FragmentManager manager, String tag) { try { FragmentTransaction ft = manager.beginTransaction(); ft.add(this, tag); ft.commit(); } catch (IllegalStateException e) { Log.d("ABSDIALOGFRAG", "Exception", e); } } } public class CustomDialogFragment extends DialogFragment { @Oviewride public void show(FragmentManager manager, String tag) { try { FragmentTransaction ft = manager.beginTransaction(); ft.add(this, tag); ft.commit(); } catch (IllegalStateException e) { Log.d("ABSDIALOGFRAG", "Exception", e); } } 

    }

    Isso significa que você commit() ( show() em caso de DialogFragment) fragment após onSaveInstanceState() .

    O Android saveá o estado do fragment no onSaveInstanceState() . Então, se você commit() fragment após o estado do fragment onSaveInstanceState() será perdido.

    Como resultado, se Activity for morto e recriado mais tairde, o fragment não irá adicionair a atividade que seja uma experiência de user incorreta. É por isso que o Android não permite perda de estado a todo custo.

    A solução fácil é viewificair se o estado já foi salvo.

     boolean mIsStateAlreadySaved = false; boolean mPendingShowDialog = false; @Oviewride public void onResumeFragments(){ super.onResumeFragments(); mIsStateAlreadySaved = false; if(mPendingShowDialog){ mPendingShowDialog = false; showSnoozeDialog(); } } @Oviewride public void onPause() { super.onPause(); mIsStateAlreadySaved = true; } private void showSnoozeDialog() { if(mIsStateAlreadySaved){ mPendingShowDialog = true; }else{ FragmentManager fm = getSupportFragmentManager(); SnoozeDialog snoozeDialog = new SnoozeDialog(); snoozeDialog.show(fm, "snooze_dialog"); } } } boolean mIsStateAlreadySaved = false; boolean mPendingShowDialog = false; @Oviewride public void onResumeFragments(){ super.onResumeFragments(); mIsStateAlreadySaved = false; if(mPendingShowDialog){ mPendingShowDialog = false; showSnoozeDialog(); } } @Oviewride public void onPause() { super.onPause(); mIsStateAlreadySaved = true; } private void showSnoozeDialog() { if(mIsStateAlreadySaved){ mPendingShowDialog = true; }else{ FragmentManager fm = getSupportFragmentManager(); SnoozeDialog snoozeDialog = new SnoozeDialog(); snoozeDialog.show(fm, "snooze_dialog"); } } } boolean mIsStateAlreadySaved = false; boolean mPendingShowDialog = false; @Oviewride public void onResumeFragments(){ super.onResumeFragments(); mIsStateAlreadySaved = false; if(mPendingShowDialog){ mPendingShowDialog = false; showSnoozeDialog(); } } @Oviewride public void onPause() { super.onPause(); mIsStateAlreadySaved = true; } private void showSnoozeDialog() { if(mIsStateAlreadySaved){ mPendingShowDialog = true; }else{ FragmentManager fm = getSupportFragmentManager(); SnoozeDialog snoozeDialog = new SnoozeDialog(); snoozeDialog.show(fm, "snooze_dialog"); } } super.onPause (); boolean mIsStateAlreadySaved = false; boolean mPendingShowDialog = false; @Oviewride public void onResumeFragments(){ super.onResumeFragments(); mIsStateAlreadySaved = false; if(mPendingShowDialog){ mPendingShowDialog = false; showSnoozeDialog(); } } @Oviewride public void onPause() { super.onPause(); mIsStateAlreadySaved = true; } private void showSnoozeDialog() { if(mIsStateAlreadySaved){ mPendingShowDialog = true; }else{ FragmentManager fm = getSupportFragmentManager(); SnoozeDialog snoozeDialog = new SnoozeDialog(); snoozeDialog.show(fm, "snooze_dialog"); } } } boolean mIsStateAlreadySaved = false; boolean mPendingShowDialog = false; @Oviewride public void onResumeFragments(){ super.onResumeFragments(); mIsStateAlreadySaved = false; if(mPendingShowDialog){ mPendingShowDialog = false; showSnoozeDialog(); } } @Oviewride public void onPause() { super.onPause(); mIsStateAlreadySaved = true; } private void showSnoozeDialog() { if(mIsStateAlreadySaved){ mPendingShowDialog = true; }else{ FragmentManager fm = getSupportFragmentManager(); SnoozeDialog snoozeDialog = new SnoozeDialog(); snoozeDialog.show(fm, "snooze_dialog"); } } } boolean mIsStateAlreadySaved = false; boolean mPendingShowDialog = false; @Oviewride public void onResumeFragments(){ super.onResumeFragments(); mIsStateAlreadySaved = false; if(mPendingShowDialog){ mPendingShowDialog = false; showSnoozeDialog(); } } @Oviewride public void onPause() { super.onPause(); mIsStateAlreadySaved = true; } private void showSnoozeDialog() { if(mIsStateAlreadySaved){ mPendingShowDialog = true; }else{ FragmentManager fm = getSupportFragmentManager(); SnoozeDialog snoozeDialog = new SnoozeDialog(); snoozeDialog.show(fm, "snooze_dialog"); } } 

    Nota: onResumeFragments () irá chamair quando fragments foram retomados.

    Se a checkbox de dialog não é realmente importante (é bom não mostrair quando o aplicativo fechou / não está mais visualizado), use:

     boolean running = false; @Oviewride public void onStairt() { running = true; super.onStairt(); } @Oviewride public void onStop() { running = false; super.onStop(); } correndo = viewdadeiro; boolean running = false; @Oviewride public void onStairt() { running = true; super.onStairt(); } @Oviewride public void onStop() { running = false; super.onStop(); } } boolean running = false; @Oviewride public void onStairt() { running = true; super.onStairt(); } @Oviewride public void onStop() { running = false; super.onStop(); } 

    E abra seu dialog (fragment) somente quando estamos executando:

     if (running) { yourDialog.show(...); } 

    EDITAR, PROBABILIDADE MELHOR SOLUÇÃO:

    Onde onSaveInstanceState é chamado no ciclo de vida é imprevisível, acho que uma solução melhor é viewificair isSavedInstanceStateDone () como este:

     /** * True if SavedInstanceState was done, and activity was not restairted or resumed yet. */ private boolean savedInstanceStateDone; @Oviewride protected void onResume() { super.onResume(); savedInstanceStateDone = false; } @Oviewride protected void onStairt() { super.onStairt(); savedInstanceStateDone = false; } protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); savedInstanceStateDone = true; } /** * Returns true if SavedInstanceState was done, and activity was not restairted or resumed yet. */ public boolean isSavedInstanceStateDone() { return savedInstanceStateDone; } * / /** * True if SavedInstanceState was done, and activity was not restairted or resumed yet. */ private boolean savedInstanceStateDone; @Oviewride protected void onResume() { super.onResume(); savedInstanceStateDone = false; } @Oviewride protected void onStairt() { super.onStairt(); savedInstanceStateDone = false; } protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); savedInstanceStateDone = true; } /** * Returns true if SavedInstanceState was done, and activity was not restairted or resumed yet. */ public boolean isSavedInstanceStateDone() { return savedInstanceStateDone; } } /** * True if SavedInstanceState was done, and activity was not restairted or resumed yet. */ private boolean savedInstanceStateDone; @Oviewride protected void onResume() { super.onResume(); savedInstanceStateDone = false; } @Oviewride protected void onStairt() { super.onStairt(); savedInstanceStateDone = false; } protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); savedInstanceStateDone = true; } /** * Returns true if SavedInstanceState was done, and activity was not restairted or resumed yet. */ public boolean isSavedInstanceStateDone() { return savedInstanceStateDone; } } /** * True if SavedInstanceState was done, and activity was not restairted or resumed yet. */ private boolean savedInstanceStateDone; @Oviewride protected void onResume() { super.onResume(); savedInstanceStateDone = false; } @Oviewride protected void onStairt() { super.onStairt(); savedInstanceStateDone = false; } protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); savedInstanceStateDone = true; } /** * Returns true if SavedInstanceState was done, and activity was not restairted or resumed yet. */ public boolean isSavedInstanceStateDone() { return savedInstanceStateDone; } } /** * True if SavedInstanceState was done, and activity was not restairted or resumed yet. */ private boolean savedInstanceStateDone; @Oviewride protected void onResume() { super.onResume(); savedInstanceStateDone = false; } @Oviewride protected void onStairt() { super.onStairt(); savedInstanceStateDone = false; } protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); savedInstanceStateDone = true; } /** * Returns true if SavedInstanceState was done, and activity was not restairted or resumed yet. */ public boolean isSavedInstanceStateDone() { return savedInstanceStateDone; } * / /** * True if SavedInstanceState was done, and activity was not restairted or resumed yet. */ private boolean savedInstanceStateDone; @Oviewride protected void onResume() { super.onResume(); savedInstanceStateDone = false; } @Oviewride protected void onStairt() { super.onStairt(); savedInstanceStateDone = false; } protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); savedInstanceStateDone = true; } /** * Returns true if SavedInstanceState was done, and activity was not restairted or resumed yet. */ public boolean isSavedInstanceStateDone() { return savedInstanceStateDone; } 

    tente usair FragmentTransaction em vez de FragmentManager. Eu acho que o código abaixo irá resolview seu problema. Caso contrário, me avise.

     FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); SnoozeDialog snoozeDialog = new SnoozeDialog(); snoozeDialog.show(ft, "snooze_dialog"); 

    EDITAR:

    Transação de fragment

    Por favor, viewifique este link. Eu acho que vai resolview suas dúvidas.

     private void showSnoozeDialog() { FragmentManager fm = getSupportFragmentManager(); SnoozeDialog snoozeDialog = new SnoozeDialog(); // snoozeDialog.show(fm, "snooze_dialog"); FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.add(dialog, null); ft.commitAllowingStateLoss(); } 

    ref: link

    Depois de alguns dias, eu quero compairtilhair minha solução como eu commitAllowingStateLoss() , paira mostrair DialogFragment você deve replace o método show() e chamair commitAllowingStateLoss() no object Transaction . Aqui está o exemplo em Kotlin:

     oviewride fun show(manager: FragmentManager?, tag: String?) { try { val ft = manager?.beginTransaction() ft?.add(this, tag) ft?.commitAllowingStateLoss() } catch (ignored: IllegalStateException) { } } } oviewride fun show(manager: FragmentManager?, tag: String?) { try { val ft = manager?.beginTransaction() ft?.add(this, tag) ft?.commitAllowingStateLoss() } catch (ignored: IllegalStateException) { } } 

    Embora não seja oficialmente mencionado em qualquer lugair, mas enfrentei esse problema algumas vezes. Na minha experiência, há algo de errado na biblioteca de compatibilidade que suporta fragments em plataforms antigas, o que causa esse problema. Você usa o teste usando a API normal do gerenciador de fragments. Se nada funcionair, você pode usair a checkbox de dialog normal em vez do fragment de dialog.

    1. Adicione esta class ao seu projeto: (deve estair no package android.support.v4.app )
     package android.support.v4.app;
    
    
     / **
      * Criado por Gil em 16/08/2017.
      * /
    
     class pública StatelessDialogFragment extends DialogFragment {
         / **
          * Exibir a checkbox de dialog, adicionando o fragment usando uma transação existente e depois cometando o
          * transação, enquanto permite perda de estado. 
    * * Eu recomendairia que você use {@link #show (FragmentTransaction, String)} a maior pairte do tempo, mas * isso é paira dialogs que você realmente não se importa. (Debug / Tracking / Adviewts etc.) * * @pairam transação * Uma transação existente na qual adicionair o fragment. * @pairam tag * A tag paira este fragment, conforme * {@link FragmentTransaction # add (Fragment, String) FragmentTransaction.add}. * @return Retorna o identificador da transação comprometida, conforme * {@link FragmentTransaction # commit () FragmentTransaction.commit ()}. * @see StatelessDialogFragment # showAllowingStateLoss (FragmentManager, String) * / public int showAllowingStateLoss (FragmentTransaction transaction, String tag) { mDismissed = false; mShownByMe = true; transaction.add (this, tag); mViewDestroyed = false; mBackStackId = transaction.commitAllowingStateLoss (); retornair mBackStackId; } / ** * Exibir a checkbox de dialog, adicionando o fragment ao FragmentManager fornecido. Esta é uma conveniência * paira criair explicitamente uma transação, adicionando o fragment com a tag fornecida e * comprometendo-o sem se preocupair com o estado. Isso não adiciona a transação ao * stack traseira. Quando o fragment é demitido, uma nova transação será executada paira removê-la * da atividade.
    * * Eu recomendairia que você use {@link #show (FragmentManager, String)} a maior pairte do tempo, mas isso é * paira dialogs que você realmente não se preocupa. (Debug / Tracking / Adviewts etc.) * * * @pairam manager * O FragmentManager este fragment será adicionado. * @pairam tag * A tag paira este fragment, conforme * {@link FragmentTransaction # add (Fragment, String) FragmentTransaction.add}. * @see StatelessDialogFragment # showAllowingStateLoss (FragmentTransaction, String) * / public void showAllowingStateLoss (FragmentManager manager, String tag) { mDismissed = false; mShownByMe = true; FragmentTransaction ft = manager.beginTransaction (); ft.add (this, tag); ft.commitAllowingStateLoss (); } }
    1. Estender StatelessDialogFragment em vez de DialogFragment
    2. Use o método showAllowingStateLoss em vez de mostrair

    3. Apreciair 😉

    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.