it-swarm.com.de

"Fehler beim Liefern des Ergebnisses" - onActivityResult

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)
72
KickingLettuce

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 FragmentTransactions 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).

286
Alex Lockwood

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
    }
}
1
vovahost