Ich habe eine LoginActivity
(Benutzeranmeldung). Es ist im Grunde genommen ein eigenes Activity
Thema, das wie ein Dialog thematisiert ist (um als Dialog zu erscheinen). Es erscheint über a SherlockFragmentActivity
. Was ich möchte ist: Wenn es eine erfolgreiche Anmeldung gibt, sollten zwei vorhanden sein FragmentTransaction
, um die Ansicht zu aktualisieren. Hier ist der Code:
Bei LoginActivity
erfolgreicher Anmeldung
setResult(1, new Intent());
In SherlockFragmentActivity
:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == 1) {
LoggedStatus = PrefActivity.getUserLoggedInStatus(this);
FragmentTransaction t = MainFragmentActivity.this.getSupportFragmentManager().beginTransaction();
SherlockListFragment mFrag = new MasterFragment();
t.replace(R.id.menu_frame, mFrag);
t.commit();
// Set up Main Screen
FragmentTransaction t2 = MainFragmentActivity.this.getSupportFragmentManager().beginTransaction();
SherlockListFragment mainFrag = new FeaturedFragment();
t2.replace(R.id.main_frag, mainFrag);
t2.commit();
}
}
Es stürzt beim ersten Commit mit diesem LogCat ab:
E/AndroidRuntime(32072): Caused by: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
E/AndroidRuntime(32072): at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1299)
E/AndroidRuntime(32072): at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1310)
E/AndroidRuntime(32072): at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:541)
E/AndroidRuntime(32072): at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:525)
E/AndroidRuntime(32072): at com.kickinglettuce.rate_this.MainFragmentActivity.onActivityResult(MainFragmentActivity.java:243)
E/AndroidRuntime(32072): at android.app.Activity.dispatchActivityResult(Activity.java:5293)
E/AndroidRuntime(32072): at android.app.ActivityThread.deliverResults(ActivityThread.java:3315)
android
android-intent
android-activity
android-fragmentactivity
TheLettuceMaster
quelle
quelle
Antworten:
Zuallererst sollten Sie meinen Blog-Beitrag lesen, um weitere Informationen zu erhalten (er spricht darüber, warum diese Ausnahme auftritt und was Sie tun können, um sie zu verhindern).
Anrufen
commitAllowingStateLoss()
ist eher ein Hack als ein Fix. Staatsverlust ist schlecht und sollte unter allen Umständen vermieden werden. Zum ZeitpunktonActivityResult()
des Aufrufs wurde der Status der Aktivität / des Fragments möglicherweise noch nicht wiederhergestellt. Daher gehen alle Transaktionen, die während dieser Zeit stattfinden, verloren. Dies ist ein sehr wichtiger Fehler, der behoben werden muss! (Beachten Sie, dass der Fehler nur auftritt, wenn SieActivity
zurückkommen, nachdem Sie vom System getötet wurden. Dies kann je nach Speicherplatz des Geräts manchmal selten sein. Diese Art von Fehler ist also nicht vorhanden sehr leicht zu fangen beim Testen).Versuchen Sie
onPostResume()
stattdessen, Ihre Transaktionen zu verschieben (beachten Sie, dassonPostResume()
immer nachonResume()
undonResume()
immer nach aufgerufen wirdonActivityResult()
):private boolean mReturningWithResult = false; @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); mReturningWithResult = true; } @Override protected void onPostResume() { super.onPostResume(); if (mReturningWithResult) { // Commit your transactions here. } // Reset the boolean flag back to false for next time. mReturningWithResult = false; }
Dies mag etwas seltsam erscheinen, aber dies ist erforderlich, um sicherzustellen, dass Ihre
FragmentTransaction
s immer festgeschrieben werden, nachdem derActivity
ursprüngliche Status wiederhergestellt wurde (onPostResume()
wird garantiert aufgerufen, nachdem derActivity
Status wiederhergestellt wurde). .quelle
Fragment#onResume()
ist in Ordnung. Dies liegt daran, dassFragmentActivity#onPostResume()
AufrufeFragmentActivity#onResumeFragments()
, welche AufrufeFragmentManager#dispatchResume()
, welcheFragment#onResume()
für jedes der Fragmente der Aktivität aufrufen. DaherFragment#onResume()
wird nach aufgerufen,FragmentActivity#onPostResume()
damit es kein Problem gibt (Sie können den [Quellcode] ( goo.gl/Lo1Z1T ) für die jeweilige Klasse überprüfen, um dies selbst zu überprüfen ... oder Sie können einfach nur mich: P. ). Und danke! Ich bin froh, dass du sie für aufschlussreich gehalten hast. :)dismiss()
nicht im Inneren aufgerufen wirdAsyncTask#onPostExecute()
(der Dialog wird automatisch von demFragmentManager
für den Fall geschlossen, dass die Aktivität im Hintergrund ausgeführt wird Sie müssen den Dialog also nicht selbst schließen, nachdem die Aktivität ohnehin beendet wurde.onPostResume()
. Das Problem wurde behoben (ich habe ein Dialogfragment erstellt,onResume()
nachdem ein Systemdialog aus einer ausstehenden Absicht abgebrochen wurde, wodurch meine App abgestürzt ist).Dies ähnelt der Antwort von @Alex Lockwood, verwendet jedoch Folgendes
Runnable
:private Runnable mOnActivityResultTask; @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); mOnActivityResultTask = new Runnable() { @Override public void run() { // Your code here } } } @Override protected void onPostResume() { super.onPostResume(); if (mOnActivityResultTask != null) { mOnActivityResultTask.run(); mOnActivityResultTask = null; } }
Wenn Sie Android 3.0 und höher mit Lambdas ausführen , verwenden Sie Folgendes :
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); mOnActivityResultTask = () -> { // Your code here } }
quelle
Sie können
ft.commitAllowingStateLoss()
dieses Problem lösen.Grund: Ihre
ft.commit()
Methode wurde nach umgeschaltetonSaveInstanceState
.quelle
Ihr Logcat sagt eindeutig: "Diese Aktion kann nach onSaveInstanceState nicht ausgeführt werden" - Sie
Activity
sind zu diesem Zeitpunkt bereits tot und konnten keine Ergebnisse zurückgeben.Beweg dich einfach:
Intent in = new Intent(); setResult(1, in);
zu dem Ort in deinem, an
Activity
dem es noch lebt, und alles wird gut. und vergessenfinish()
Sie nichtActivity
, das Ergebnis zu liefern.quelle
finish()
ist das Letzte, was ich tue. Ich hatte den Absichtscode direkt darüber. Ich habe ihn nach oben verschoben und den gleichen Fehler. IchIn meinem Fall hatte ich aus folgenden Gründen die gleichen Probleme
public void onBackPressed() { super.onBackPressed(); setIntents(); } private void setIntents(){ Intent searchConstaints=new Intent(); searchConstaints.putExtra("min",20); searchConstaints.putExtra("max",80); setResult(101,searchConstaints); finish(); }
Gelöst durch Neuanordnen der Funktion Aufrufe in onBackPressed ()
public void onBackPressed() { setIntents(); super.onBackPressed(); }
quelle