“Fout bij leveren van resultaat” – onActivityForResult

Ik heb een LoginActivity(gebruiker logt in). Het is in feite zijn eigen Activitymet een thema als een dialoogvenster (om te verschijnen als een dialoogvenster). Het verschijnt boven een SherlockFragmentActivity. Wat ik wil is: als er een succesvolle login is, zouden er twee FragmentTransaction‘s moeten zijn om de weergave bij te werken. Hier is de code:

In LoginActivity, indien succesvol inloggen,

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

Het crasht bij de eerste commit, met deze LogCat:

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)

Antwoord 1, autoriteit 100%

Allereerst moet je mijn blogberichtvoor meer informatie (het vertelt waarom deze uitzondering optreedt en wat u kunt doen om dit te voorkomen).

Het aanroepen van commitAllowingStateLoss()is meer een hack dan een oplossing. Staatsverlies is slecht en moet koste wat kost worden vermeden. Op het moment dat onActivityResult()wordt aangeroepen, is de status van de activiteit/het fragment mogelijk nog niet hersteld, en daarom gaan alle transacties die gedurende deze tijd plaatsvinden verloren. Dit is een zeer belangrijke bug die moet worden aangepakt! (Merk op dat de bug alleen optreedt wanneer uw Activityterugkomt nadat deze door het systeem is uitgeschakeld… wat, afhankelijk van hoeveel geheugen het apparaat heeft, soms zeldzaam kan zijn… dus dit soort bug is niet iets dat heel gemakkelijk te ontdekken is tijdens het testen).

Probeer in plaats daarvan uw transacties te verplaatsen naar onPostResume()(merk op dat onPostResume()altijd wordt aangeroepen na onResume()en onResume()wordt altijd aangeroepen na 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;
}

Dit lijkt misschien een beetje raar, maar dit soort dingen doen is nodig om ervoor te zorgen dat uw FragmentTransaction‘s altijd worden vastgelegd nade Activity‘s staat is hersteld naar zijn oorspronkelijke staat (onPostResume()wordt gegarandeerd aangeroepen nadat de status van de Activityis hersteld).


Antwoord 2

Dit is vergelijkbaar met het antwoord van @Alex Lockwood, maar met een 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;
    }
}

Als je Android 3.0en hoger gebruikt met lambdas, gebruik dan dit:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    mOnActivityResultTask = () -> {
        // Your code here
    }
}

Antwoord 3

U kunt ft.commitAllowingStateLoss()gebruiken om dit probleem op te lossen.

Reden: uw methode ft.commit()is gewijzigd na onSaveInstanceState.


Antwoord 4

uw logcat zegt duidelijk: “Kan deze actie niet uitvoeren na onSaveInstanceState”— uw Activityis op dat moment al dood en kon geen resultaten retourneren.

p>

gewoon verplaatsen:

Intent in = new Intent();
setResult(1, in);

naar de plaats in je Activitywaar het nog steeds leeft, en alles komt goed.
en vergeet niet je Activityte Activityom het resultaat te leveren.


Antwoord 5

In mijn geval had ik dezelfde problemen vanwege het volgende

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

Opgelost door de functie Aanroepen te herschikken binnen onBackPressed()

public void onBackPressed() {
    setIntents();
    super.onBackPressed();
}

Other episodes