webentwicklung-frage-antwort-db.com.de

"Kann diese Aktion nicht nach onSaveInstanceState ausführen" - Warum erhalte ich diese Ausnahme von der onResume-Methode meiner Aktivität?

Meine Aktivität ruft die Kamera mit der Absicht ACTION_IMAGE_CAPTURE auf. Wenn die Kameraaktivität erfolgreich zurückkehrt, setze ich im onActivityResult-Callback ein Flag, und basierend auf dem Wert des Flag starte ich ein Fragment in meinem onResume, um dem aufgenommenen Bild eine Beschriftung hinzuzufügen. Das scheint ok zu funktionieren. 

Ich habe gerade eine Stack-Spur von der "wilden" Beschwerde bekommen, die sich darüber beklagt, dass ich versucht habe, eine Fragmenttransaktion auszuführen, nachdem onSaveInstanceState aufgerufen wurde. Aber ich mache das Festschreiben in meiner onResume-Methode! Warum sollte sich Android darüber beschweren? Ich habe Android: configChanges = "Orientierung | keyboardHidden | keyboard | screenSize" in meiner AndroidManifest.xml gesetzt, so dass eine Orientierungsänderung dies nicht auslösen sollte ....

Dies trat auf einem Samsung Galaxy S3 (SGH-i747) mit 4.0.4 auf

Hier ist der Stapel:

Java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
    at Android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.Java:1314)
    at Android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.Java:1325)
    at Android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.Java:548)
    at Android.support.v4.app.BackStackRecord.commit(BackStackRecord.Java:532)
    at com.Familiar.Android.FamiliarAppV1.AddPhotosActivity2.performFragmentTransition(AddPhotosActivity2.Java:278)
    at com.Familiar.Android.FamiliarAppV1.AddPhotosActivity2.switchToCaptionsFragment(AddPhotosActivity2.Java:438)
    at com.Familiar.Android.FamiliarAppV1.AddPhotosActivity2.onResume(AddPhotosActivity2.Java:167)
    at Android.app.Instrumentation.callActivityOnResume(Instrumentation.Java:1158)
    at Android.app.Activity.performResume(Activity.Java:4544)
    at Android.app.ActivityThread.performResumeActivity(ActivityThread.Java:2448)
    at Android.app.ActivityThread.handleResumeActivity(ActivityThread.Java:2486)
    at Android.app.ActivityThread$H.handleMessage(ActivityThread.Java:1187)
    at Android.os.Handler.dispatchMessage(Handler.Java:99)
    at Android.os.Looper.loop(Looper.Java:137)
    at Android.app.ActivityThread.main(ActivityThread.Java:4514)
    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:980)
    at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:747)
    at dalvik.system.NativeStart.main(Native Method)

Jede Hilfe oder Weisheit wird geschätzt.

28
PacificSky

Ich denke Ich kenne die Antwort - Ich verwende die FragmentActivity von v4-Kompatibilitätsbibliothek, und daher muss ich meine Fragmenttransaktionen in onResumeFragments statt in onResume durchführen. Kann jemand das bestätigen?

54
PacificSky

sie können die Methode commitAllowingStateLoss() verwenden.

seien Sie sich jedoch bewusst, dass Sie den Status Ihrer Aktivitäten verlieren können Wie Sie in Google Android-Referenz erkennen können, erklären Sie den Unterschied zwischen den beiden auf die folgende Weise

Wie commit (), ermöglicht jedoch die Ausführung des Commits, nachdem der Status einer Aktivität gespeichert wurde. Dies ist gefährlich, da das Festschreiben verloren gehen kann, wenn die Aktivität später aus ihrem Status wiederhergestellt werden muss. Daher sollte dies nur für Fälle verwendet werden, in denen der UI-Status für den Benutzer unerwartet geändert werden kann.

meiner Erfahrung nach kann es vorkommen, dass die addToBackStack-Methode manchmal nicht funktioniert. Daher müssen Sie sie manuell in das Fragment einfügen. Natürlich wird der Status nicht gespeichert (Textfeld ext.).

12
Asaf Manassen

das hat für mich funktioniert ... habe es selbst herausgefunden ... hoffe es hilft dir!

1) KEINE globalen "statischen" FragmentManager/FragmentTransaction haben.

2) onCreate, IMMER den FragmentManager erneut initialisieren!

probe 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();
    }
}
3
kurayami88

Update Ich glaube, ich habe hier eine Erklärung und eine Lösung gefunden: http://code.google.com/p/Android/issues/detail?id=23096#c4 Ich habe das implementiert Empty Fragment Workaround wurde dort veröffentlicht und hat bisher keine IllegalStateException mehr erhalten.

Ich füge das unsichtbare Zustandsfragment so in meine Aktivität ein;

@Override
protected void onCreate(final Bundle args) {
    ...
    if (args == null) {
        final FragmentManager fm = this.getSupportFragmentManager();
        final FragmentTransaction ft = fm.beginTransaction();
        final Fragment emptyFragmentWithCallback = new EmptyFragmentWithCallbackOnResume();
        ft.add(emptyFragmentWithCallback, EmptyFragmentWithCallbackOnResume.TAG);
        ft.commit();
    }

Der folgende Code stammt aus dem obigen Link:

public class EmptyFragmentWithCallbackOnResume extends Fragment {
OnFragmentAttachedListener mListener = null;

@Override
public void onAttach(SupportActivity activity) {
    super.onAttach(activity);
    try {
        mListener = (OnFragmentAttachedListener) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString() + " must implement OnFragmentAttachedListener");
    }
}

@Override
public void onResume() {
    super.onResume();
    if (mListener != null) {
        mListener.OnFragmentAttached();
    }
}

public interface OnFragmentAttachedListener {
    public void OnFragmentAttached();
}
}

und rufen Fragmenttransaktionen auf, die intuitiv in onResume oder onResumeFragments in meine benutzerdefinierte onFragmentAttached -Methode eingehen, die vom unsichtbaren Statusfragment aufgerufen wird. Ich verwende onResumeFragments überhaupt nicht und gebe keine Fragmenttransaktionen in onResume aus.

Also zusammenfassend. Wenn Sie die Unterstützung lib und Fragmente verwenden, vergessen Sie onResume ziemlich, vergessen Sie onResumeFragments und implementieren Sie Ihr eigenes "onResume", das auf der obigen Problemumgehung basiert. Dies ist etwas lächerlich. 


Kann ich nicht bestätigen Ich habe genau das gleiche Problem. Auch wenn ich eine Fragmenttransaktion in onResumeFragments ausstelle .. __ Dies funktionierte, wie ich hier gepostet habe: IllegalStateException - Fragment-Unterstützungsbibliothek

Es scheint, dass der Fehler nur bei 4.0.3 und 4.0.4 auftritt. Es kommt jedoch weder immer noch in meinem Emulator vor.

Ich verwende Support lib rev. 10 und API 16 ... Ich rufe DialogFragment.show in onResumeFragments auf und bekomme diese lächerliche Ausnahme von einigen zufälligen Benutzern. Ich kann es nicht lokal reproduzieren. 

2
phlebas

Ich entwickle zunächst meine App für Android 2.2 (SDK 8) mit der Support-v4-Bibliothek. Als ich sie mit 4.2 (SDK 17) verwende, hatte ich dieselben Probleme mit meinen Fragmenten. Aber mein Manifest zu Android ändern: minSdkVersion = "8" Android: targetSdkVersion = "17", meine Probleme gelöst. Vielleicht hepls dich auch.

1
Andre Rocha

Ich bekam dies immer, als ich versuchte, ein Fragment in der onActivityForResult () -Methode anzuzeigen. Das Problem war also das nächste:

  1. Meine Aktivität wurde angehalten und gestoppt, was bedeutet, dass onSaveInstanceState () bereits aufgerufen wurde (sowohl für Geräte vor Honeycomb als auch für Geräte nach Honeycomb).
  2. Im Falle eines Ergebnisses habe ich eine Transaktion ausgeführt, um das Fragment anzuzeigen/auszublenden, wodurch diese IllegalStateException verursacht wird.

Was ich gemacht habe, ist als nächstes:

  1. Mehrwert für die Ermittlung, ob die gewünschte Aktion ausgeführt wurde (z. B. Foto von camere aufnehmen - isPhotoTaken) - es kann ein boolescher oder ganzzahliger Wert sein, je nachdem, wie viele verschiedene Transaktionen Sie benötigen.
  2. Beim Überschreiben der onResumeFragments () -Methode habe ich nach meinem Wert gesucht und nach Fragmentierungstransaktionen die ich brauchte. In diesem Fall wurde commit () nicht nach onSaveInstanceState ausgeführt, da der Status in der onResumeFragments () -Methode zurückgegeben wurde.
1
Array

Fügen Sie dies zu Ihrer Aktivität hinzu:

 @Override
    protected void onSaveInstanceState(Bundle outState) {
        //No call for super(). Bug on API Level > 11.
    }
0
Alok Singh