370 Stimmen

erhält die Ausnahme "IllegalStateException: Kann diese Aktion nach onSaveInstanceState nicht ausführen"

Ich habe eine Live-Android-Anwendung, und aus dem Markt habe ich folgende Stack-Trace erhalten und ich habe keine Ahnung, warum seine geschieht, wie seine nicht in Anwendungscode geschieht, aber seine immer verursacht durch einige oder das andere Ereignis aus der Anwendung (Annahme)

Ich verwende keine Fragmente, dennoch gibt es einen Verweis auf FragmentManager. Wenn jeder Körper kann etwas Licht auf einige versteckte Fakten werfen, um diese Art von Problem zu vermeiden:

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1109)
at android.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:399)
at android.app.Activity.onBackPressed(Activity.java:2066)
at android.app.Activity.onKeyDown(Activity.java:1962)
at android.view.KeyEvent.dispatch(KeyEvent.java:2482)
at android.app.Activity.dispatchKeyEvent(Activity.java:2274)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1668)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchKeyEvent(PhoneWindow.java:1720)
at com.android.internal.policy.impl.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1258)
at android.app.Activity.dispatchKeyEvent(Activity.java:2269)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1668)
at android.view.ViewRoot.deliverKeyEventPostIme(ViewRoot.java:2851)
at android.view.ViewRoot.handleFinishedEvent(ViewRoot.java:2824)
at android.view.ViewRoot.handleMessage(ViewRoot.java:2011)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:132)
at android.app.ActivityThread.main(ActivityThread.java:4025)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:491)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
at dalvik.system.NativeStart.main(Native Method)

18voto

Basbous Punkte 3924

Kurze und funktionierende Lösung :

Folgen Sie einfachen Schritten:

Schritt 1 : Überschreiben Sie den onSaveInstanceState-Zustand im jeweiligen Fragment. Und entfernen Sie die Super-Methode daraus.

@Override
public void onSaveInstanceState(Bundle outState) {
};

Schritt 2 : Verwenden Sie CommitAllowingStateLoss(); anstelle von commit(); bei Fragmentierungsoperationen.

fragmentTransaction.commitAllowingStateLoss();

13voto

Metwalli Punkte 1831

Ich denke, dass der Lifecycle-Status helfen kann, solche Abstürze zu verhindern. Ab der Android-Support-Lib v26.1.0 können Sie die folgende Prüfung durchführen:

if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)){
  // Do fragment's transaction commit
}

oder Sie können es versuchen:

Fragment.isStateSaved()

mehr Informationen hier [https://developer.Android.com/reference/Android/support/v4/app/Fragment.html#isStateSaved()](https://developer.android.com/reference/android/support/v4/app/Fragment.html#isStateSaved())

7voto

kurayami88 Punkte 121

Das hat bei mir funktioniert... ich habe es selbst herausgefunden... ich hoffe, es hilft Ihnen!

1) NICHT über einen globalen "statischen" FragmentManager / FragmentTransaction verfügen.

2) onCreate, IMMER den FragmentManager erneut initialisieren!

Beispiel unten :-

public abstract class FragmentController extends AnotherActivity{
protected FragmentManager fragmentManager;
protected FragmentTransaction fragmentTransaction;
protected Bundle mSavedInstanceState;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mSavedInstanceState = savedInstanceState;
    setDefaultFragments();
}

protected void setDefaultFragments() {
    fragmentManager = getSupportFragmentManager();
    //check if on orientation change.. do not re-add fragments!
    if(mSavedInstanceState == null) {
        //instantiate the fragment manager

        fragmentTransaction = fragmentManager.beginTransaction();

        //the navigation fragments
        NavigationFragment navFrag = new NavigationFragment();
        ToolbarFragment toolFrag = new ToolbarFragment();

        fragmentTransaction.add(R.id.NavLayout, navFrag, "NavFrag");
        fragmentTransaction.add(R.id.ToolbarLayout, toolFrag, "ToolFrag");
        fragmentTransaction.commitAllowingStateLoss();

        //add own fragment to the nav (abstract method)
        setOwnFragment();
    }
}

6voto

Oleg Novosad Punkte 2138

Ich war immer erhalten diese, wenn ich versucht, Fragment in onActivityForResult()-Methode zeigen, so dass das Problem nächste war:

  1. Meine Activity ist pausiert und gestoppt, was bedeutet, dass onSaveInstanceState() bereits aufgerufen wurde (sowohl für pre-Honeycomb als auch post-Honeycomb Geräte).
  2. Im Falle eines Ergebnisses habe ich eine Transaktion zum Ein-/Ausblenden des Fragments durchgeführt, die diese IllegalStateException verursacht.

Was ich gemacht habe, ist das Nächste:

  1. Zusätzlicher Wert zur Bestimmung, ob die gewünschte Aktion durchgeführt wurde (z.B. Aufnahme eines Fotos von der Kamera - isPhotoTaken) - es kann ein boolescher oder ganzzahliger Wert sein, je nachdem, wie viele verschiedene Transaktionen Sie benötigen.
  2. In der überschriebenen onResumeFragments()-Methode überprüfte ich meinen Wert und führte danach die benötigten Fragmenttransaktionen durch. In diesem Fall wurde commit() nicht nach onSaveInstanceState durchgeführt, da der Zustand in der Methode onResumeFragments() zurückgegeben wurde.

5voto

douggynix Punkte 141

Ich habe das Problem mit onconfigurationchanged gelöst. Der Trick ist, dass nach Android Aktivität Lebenszyklus, wenn Sie explizit eine Absicht (Kamera Absicht, oder jede andere) genannt; die Aktivität wird angehalten und onsavedInstance wird in diesem Fall aufgerufen. Wenn das Gerät in eine andere Position gedreht wird als die, in der die Aktivität aktiv war, führt die Ausführung von Fragmentoperationen wie Fragment-Commit zu einer Illegal State Exception. Es gibt eine Menge Beschwerden darüber. Es hat etwas mit dem Lebenszyklusmanagement von Android-Aktivitäten und den richtigen Methodenaufrufen zu tun. Um das Problem zu lösen, habe ich dies getan: 1-Überschreiben Sie die onsavedInstance-Methode Ihrer Aktivität, und bestimmen Sie die aktuelle Bildschirmausrichtung (Hoch- oder Querformat) dann setzen Sie Ihre Bildschirmausrichtung, bevor Ihre Aktivität angehalten wird. auf diese Weise die Aktivität, die Sie sperren die Bildschirmdrehung für Ihre Aktivität für den Fall, dass es von einem anderen gedreht wurde. 2. Überschreiben Sie dann die onresume-Methode der Aktivität und setzen Sie Ihren Orientierungsmodus jetzt auf Sensor, so dass er nach dem Aufruf der onsaved-Methode ein weiteres Mal onconfiguration aufruft, um die Drehung richtig zu behandeln.

Sie können diesen Code kopieren und in Ihre Aktivität einfügen, um ihn zu bearbeiten:

@Override
protected void onSaveInstanceState(Bundle outState) {       
    super.onSaveInstanceState(outState);

    Toast.makeText(this, "Activity OnResume(): Lock Screen Orientation ", Toast.LENGTH_LONG).show();
    int orientation =this.getDisplayOrientation();
    //Lock the screen orientation to the current display orientation : Landscape or Potrait
    this.setRequestedOrientation(orientation);
}

//A method found in stackOverflow, don't remember the author, to determine the right screen orientation independently of the phone or tablet device 
public int getDisplayOrientation() {
    Display getOrient = getWindowManager().getDefaultDisplay();

    int orientation = getOrient.getOrientation();

    // Sometimes you may get undefined orientation Value is 0
    // simple logic solves the problem compare the screen
    // X,Y Co-ordinates and determine the Orientation in such cases
    if (orientation == Configuration.ORIENTATION_UNDEFINED) {
        Configuration config = getResources().getConfiguration();
        orientation = config.orientation;

        if (orientation == Configuration.ORIENTATION_UNDEFINED) {
        // if height and widht of screen are equal then
        // it is square orientation
            if (getOrient.getWidth() == getOrient.getHeight()) {
                orientation = Configuration.ORIENTATION_SQUARE;
            } else { //if widht is less than height than it is portrait
                if (getOrient.getWidth() < getOrient.getHeight()) {
                    orientation = Configuration.ORIENTATION_PORTRAIT;
                } else { // if it is not any of the above it will defineitly be landscape
                    orientation = Configuration.ORIENTATION_LANDSCAPE;
                }
            }
        }
    }
    return orientation; // return value 1 is portrait and 2 is Landscape Mode
}

@Override
public void onResume() {
    super.onResume();
    Toast.makeText(this, "Activity OnResume(): Unlock Screen Orientation ", Toast.LENGTH_LONG).show();
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X