2016-07-25 7 views
32

Die neue Methode commitNow(), die in Android N und der Support-Bibliothek Version 24 hinzugefügt wurde, weist eine begrenzte und etwas verwirrende Dokumentation auf.Wie arbeitet die neue FragmentTransaction commitNow() intern?

Übernimmt diese Transaktion synchron. Alle hinzugefügten Fragmente werden initialisiert und vollständig in den Lebenszyklus-Zustand ihres Hosts gebracht und alle entfernten Fragmente werden entsprechend abgerissen, bevor dieser Aufruf zurückkehrt. Wenn Sie eine Transaktion auf diese Weise festschreiben, können Fragmente als dedizierte, gekapselte Komponenten hinzugefügt werden, die den Lebenszyklusstatus ihres Hosts überwachen und gleichzeitig festere Bestellgarantien zur Verfügung stellen, wenn diese Fragmente vollständig initialisiert sind und bereit sind. Bei Fragmenten, die Ansichten verwalten, werden die Ansichten erstellt und angehängt.

Aufruf commitNow vorzuziehen Aufruf commit() von FragmentManager.executePendingTransactions gefolgt() als letztere wird den Nebeneffekt haben versucht, alle derzeit ausstehenden Transaktionen zu begehen, ob das das gewünschte Verhalten ist oder nicht.

auf diese Weise begangen Transaktionen können nicht auf die FragmentManager Rücken Stapel hinzugefügt werden, wie so Bestellung garantiert andere erwartet für andere asynchron begangen Transaktionen brechen würde tun. Diese Methode wird IllegalStateException auslösen, wenn die zuvor angeforderte Transaktion dem Backstack mit addToBackStack (String) hinzugefügt wurde.

Eine Transaktion kann nur mit dieser -Methode festgeschrieben werden, bevor ihre Aktivität gespeichert wird. Wenn nach diesem Punkt der Commit versucht wird, wird eine Ausnahme ausgelöst. Dies liegt daran, dass der Status nach dem Festschreiben verloren gehen kann, wenn die Aktivität aus ihrem Status wiederhergestellt werden muss. Siehe commitAllowingStateLoss() für Situationen, in denen es in Ordnung sein kann, das Commit zu verlieren.

Ich habe den Teil fett hervorgehoben, den ich denke, dass es verwirrend ist.

Also, mein Hauptanliegen/Fragen sind:

1 - Sie dürfen nicht hinzugefügt werden? Es sagt, dass ich eine IllegalStateException bekommen werde, also wird es oder wird nicht hinzugefügt werden?

2 - Ich akzeptiere die Tatsache, dass ich das nicht verwenden kann, wenn wir ein Fragment im Backstack hinzufügen möchten. Was sie nicht sagen, ist, dass Sie diese Ausnahme erhalten:

java.lang.IllegalStateException: This transaction is already being added to the back stack 

!!!! ????

Also kann ich nicht addToBackStack(String) selbst anrufen, weil es intern es für mich anruft? Es tut mir leid, aber ... was? Warum? Was ist, wenn ich nicht möchte, dass es im Backstack hinzugefügt wird? Und was, wenn ich später versuche, dieses Fragment aus dem Backstack zu verwenden, aber weil es NICHT hinzugefügt werden darf, ist es später nicht da?

Es sieht so aus, als ob etwas erwartet wird, wenn ich commitAllowingStateLoss() benutze, aber ich sehe, dass commitNowAllowingStateLoss() auch existiert, also ... welche Art von Logik folgt es?

TL; DR

Wie wird commitNow() arbeitet intern in Bezug auf die Backstack?

+0

Und jetzt 5 Monate später, noch niemand weiß! – EpicPandaForce

+0

@EpicPandaForce Beantwortet! Hoffe, meine Antwort kann Sie zufriedenstellen :) –

+0

@NikoAdrianusYuwono Ich werde das Bounty für ein bisschen länger nur um sicher zu stellen, aber es ist definitiv ein Anfang: p – EpicPandaForce

Antwort

38

Es ist eine gute Sache, dass Android-Quellcode Open Source ist, wenn wir mit einer solchen Frage konfrontiert wurden!

Antwort

Also lassen Sie uns bei BackStackRecord Quelle einen Blick here

@Override 
public void commitNow() { 
    disallowAddToBackStack(); 
    mManager.execSingleAction(this, false); 
} 

@Override 
public FragmentTransaction disallowAddToBackStack() { 
    if (mAddToBackStack) { 
     throw new IllegalStateException(
       "This transaction is already being added to the back stack"); 
    } 
    mAllowAddToBackStack = false; 
    return this; 
} 

Und mAddToBackStack wird auf true gesetzt werden, wenn Sie addToBackStack in Ihrer Transaktion aufrufen.

So, um Ihre Frage zu beantworten, wird keine addToBackStack intern aufgerufen, wenn Sie commitNow() aufrufen, ist es die Ausnahme Nachricht, die ambig ist. Ich denke, es sollte You're not allowed to add to backstack when using commitNow() stattdessen die aktuelle Nachricht sagen.

Bonus:

Wenn wir tiefer in Code FragmentManager Quelle here, graben commitNow() tatsächlich fast gleiche wie executePendingTransactions() wie oben geschrieben, sondern die Ausführung aller zuvor begangen Transaktion, commitNow() wird nur diese Transaktion verpflichten tun .

Ich denke, das ist der Hauptgrund, warum commitNow() kein Hinzufügen zum Backstack erlaubt, da es nicht garantieren kann, dass es keine andere ausstehende Transaktion gibt. Wenn commitNow() zum Backstack hinzugefügt werden kann, besteht die Möglichkeit, dass wir unsere Backstack-Sequenz aufbrechen können, die zu unerwarteten Ergebnissen führt.

+0

Also anscheinend ist die IllegalStateException-Nachricht nur falsch ... Danke Niko! – Kaizie

+0

@Kaizie Sie sind herzlich willkommen! Bitte akzeptieren Sie die Antwort, wenn Sie denken, dass es richtig ist :) –

+1

Ja, die Überprüfung des Quellcodes sieht aus wie es ist die richtige Antwort. Aber irgendwie habe ich das Gefühl, dass sie diese neue API in Google IO überverkauft haben ... weil sie versucht haben, es als die erstaunliche Lösung für das Fragment IllegalStateException Problem nach der Aktivitätspause zu verkaufen, aber irgendwie bietet das nicht die vollen commit() Funktionen, weil du kannst es nicht zum Backstack hinzufügen ... also kann es nur in bestimmten Situationen verwendet werden, wenn deine App es erlaubt, dieses Fragment hinzuzufügen, ohne es dem Backstack hinzuzufügen ... Wie auch immer, korrekte Antwort! Vielen Dank! – Kaizie