Ich habe ein LoginActivity
(Benutzer meldet sich an). Es ist im Grunde sein eigenes Activity
, das wie ein Dialog thematisiert ist (so als ob ein Dialog erscheinen würde). Es erscheint über einem SherlockFragmentActivity
. Was ich möchte ist: Wenn es eine erfolgreiche Anmeldung gibt, sollten zwei FragmentTransaction
vorhanden sein, um die Ansicht zu aktualisieren. Hier ist der Code:
Bei erfolgreicher Anmeldung in LoginActivity
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)
Zuallererst solltest du meinen Blog-Post lesen, um weitere Informationen zu erhalten (er handelt davon, warum diese Ausnahme gilt) passiert und was Sie tun können, um dies zu verhindern).
Das Aufrufen von commitAllowingStateLoss()
ist eher ein Hack als ein Fix. Staatsverlust ist schlecht und sollte um jeden Preis vermieden werden. Zum Zeitpunkt des Aufrufs von onActivityResult()
wurde der Status der Aktivität/des Fragments möglicherweise noch nicht wiederhergestellt, sodass alle Transaktionen, die während dieser Zeit stattfinden, verloren gehen. Dies ist ein sehr wichtiger Fehler, der behoben werden muss! (Beachten Sie, dass der Fehler nur dann auftritt, wenn Ihr Activity
zurückkommt, nachdem er vom System getötet wurde. Dies kann je nach dem, wie viel Speicher das Gerät hat, manchmal selten sein.) Fehler ist nicht sehr einfach beim Testen zu finden).
Versuchen Sie stattdessen, Ihre Transaktionen in onPostResume()
zu verschieben (beachten Sie, dass onPostResume()
immer nach onResume()
und onResume()
immer nach onActivityResult()
):
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 es ist notwendig, dies zu tun, um sicherzustellen, dass Ihre FragmentTransaction
s immer festgeschrieben werden after Der Zustand von Activity
wurde wiederhergestellt sein ursprünglicher Zustand (onPostResume()
wird garantiert aufgerufen, nachdem der Zustand des Activity
wiederhergestellt wurde).
Dies ähnelt der Antwort von @Alex Lockwood, verwendet jedoch ein 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;
}
}
Falls Sie Android 3. 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
}
}