Transakcje z fragmentem kodu

W czasie wykonywania kodu FragmentManager może on dodawać, usuwać i zastępować fragmenty oraz wykonywać inne działania w odpowiedzi na interakcje użytkownika. Każdy zestaw zmian fragmentu, który zatwierdzisz, nazywa się transakcją. Możesz określić, co ma się dziać w ramach transakcji, korzystając z interfejsów API udostępnionych przez klasę FragmentTransaction. W jednej transakcji możesz zgrupować wiele działań – na przykład transakcja może dodać lub zastąpić wiele fragmentów. Takie grupowanie może być przydatne, gdy na tym samym ekranie wyświetla się kilka elementów wyższego rzędu, np. w przypadku widoku podzielonego.

Każdą transakcję możesz zapisać w steku zarządzania FragmentManager, aby umożliwić użytkownikowi cofanie się do poprzednich zmian w fragmentach – podobnie jak w przypadku czynności.

Możesz uzyskać instancję FragmentTransactionFragmentManager, wywołując funkcję beginTransaction(), jak pokazano w tym przykładzie:

Kotlin

val fragmentManager = ...
val fragmentTransaction = fragmentManager.beginTransaction()

Java

FragmentManager fragmentManager = ...
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

Ostatnie wywołanie w każdym FragmentTransaction musi zatwierdzić transakcję. Wywołanie commit() sygnalizuje FragmentManager, że do transakcji zostały dodane wszystkie operacje.

Kotlin

val fragmentManager = ...
// The fragment-ktx module provides a commit block that automatically
// calls beginTransaction and commit for you.
fragmentManager.commit {
    // Add operations here
}

Java

FragmentManager fragmentManager = ...
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

// Add operations here

fragmentTransaction.commit();

Zezwalanie na zmianę kolejności zmian stanu fragmentu

Każdy FragmentTransaction powinien używać setReorderingAllowed(true):

Kotlin

supportFragmentManager.commit {
    ...
    setReorderingAllowed(true)
}

Java

FragmentManager fragmentManager = ...
fragmentManager.beginTransaction()
    ...
    .setReorderingAllowed(true)
    .commit();

Ze względu na zgodność zachowania domyślnie nie jest włączona flaga przetasowania. Konieczne jest jednak, aby FragmentManager mógł prawidłowo wykonywać FragmentTransaction, zwłaszcza gdy działa na wyższym poziomie stosu oraz uruchamia animacje i przejścia. Włączenie tej opcji powoduje, że jeśli wiele transakcji jest wykonywanych jednocześnie, żadne fragmenty pośrednie (czyli te, które są dodawane, a następnie natychmiast zastępowane) nie przechodzą przez zmiany cyklu życia ani nie są animowane ani przekształcane. Pamiętaj, że ta flaga wpływa zarówno na początkowe wykonanie transakcji, jak i na cofnięcie transakcji z popBackStack().

Dodawanie i usuwanie fragmentów

Aby dodać fragment do FragmentManager, wywołaj funkcję add() w ramach transakcji. Ta metoda otrzymuje identyfikator kontenera fragmentu oraz nazwę klasy fragmentu, który chcesz dodać. Dodany fragment zostanie przeniesiony do stanu RESUMED. Zdecydowanie zalecamy, aby kontener był elementem FragmentContainerView, który jest częścią hierarchii widoków.

Aby usunąć fragment z serwera, wywołaj funkcję remove(), podając instancję fragmentu, który został pobrany z menedżera fragmentów za pomocą funkcji findFragmentById() lub findFragmentByTag(). Jeśli widok fragmentu został wcześniej dodany do kontenera, zostanie z niego usunięty. Usunięty fragment zostaje przeniesiony do stanu DESTROYED.

Użyj polecenia replace(), aby zastąpić istniejący fragment w kontenerze instancją nowej klasy fragmentu podanej przez Ciebie. Wywołanie funkcji replace() jest równoważne wywołaniu funkcji remove() z fragmentem w kontenerze i dodaniem nowego fragmentu do tego samego kontenera.

Ten fragment kodu pokazuje, jak zastąpić jeden fragment innym:

Kotlin

// Create new fragment
val fragmentManager = // ...

// Create and commit a new transaction
fragmentManager.commit {
    setReorderingAllowed(true)
    // Replace whatever is in the fragment_container view with this fragment
    replace<ExampleFragment>(R.id.fragment_container)
}

Java

// Create new fragment and transaction
FragmentManager fragmentManager = ...
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.setReorderingAllowed(true);

// Replace whatever is in the fragment_container view with this fragment
transaction.replace(R.id.fragment_container, ExampleFragment.class, null);

// Commit the transaction
transaction.commit();

W tym przykładzie nowy element ExampleFragment zastępuje fragment, jeśli taki istnieje, który znajduje się obecnie w kontenerze układu zidentyfikowanym przez R.id.fragment_container.

Domyślnie zmiany wprowadzone w FragmentTransaction nie są dodawane do stosu wstecz. Aby zapisać te zmiany, możesz wywołać funkcję addToBackStack() w obiekcie FragmentTransaction. Więcej informacji znajdziesz w artykule Menedżer fragmentów.

Commit jest asynchroniczny

Wywołanie commit() nie spowoduje natychmiastowego wykonania transakcji. Zamiast tego jest zaplanowana data uruchomienia transakcji w głównym wątku UI, gdy tylko będzie to możliwe. Jeśli jednak jest to konieczne, możesz wywołać metodę commitNow(), by od razu uruchomić transakcję dotyczącą fragmentu w wątku interfejsu.

Pamiętaj, że commitNow jest niezgodna z addToBackStack. Możesz też wykonać wszystkie oczekujące wywołania FragmentTransactions przesłane przez wywołania commit(), które nie zostały jeszcze uruchomione, wywołując funkcję executePendingTransactions(). To podejście jest zgodne z funkcją addToBackStack.

W większości przypadków wystarczy commit().

kolejność wykonywania operacji ma znaczenie;

Kolejność wykonywania operacji w FragmentTransaction ma znaczenie, zwłaszcza podczas korzystania z funkcji setCustomAnimations(). Ta metoda stosuje określone animacje do wszystkich operacji fragmentu, które następują po niej.

Kotlin

supportFragmentManager.commit {
    setCustomAnimations(enter1, exit1, popEnter1, popExit1)
    add<ExampleFragment>(R.id.container) // gets the first animations
    setCustomAnimations(enter2, exit2, popEnter2, popExit2)
    add<ExampleFragment>(R.id.container) // gets the second animations
}

Java

getSupportFragmentManager().beginTransaction()
        .setCustomAnimations(enter1, exit1, popEnter1, popExit1)
        .add(R.id.container, ExampleFragment.class, null) // gets the first animations
        .setCustomAnimations(enter2, exit2, popEnter2, popExit2)
        .add(R.id.container, ExampleFragment.class, null) // gets the second animations
        .commit()

Ograniczanie cyklu życia fragmentu

FragmentTransactions może wpływać na stan cyklu życia poszczególnych fragmentów dodanych w ramach transakcji. Podczas tworzenia FragmentTransaction, setMaxLifecycle()określa maksymalny stan danego fragmentu. Na przykład komponent ViewPager2 używa elementu setMaxLifecycle(), aby ograniczyć fragmenty poza ekranem do stanu STARTED.

Wyświetlanie i ukrywanie widoków fragmentu

Użyj metod FragmentTransaction show() i hide() , aby wyświetlać i ukrywać widok fragmentów dodanych do kontenera. Te metody określają widoczność widoków fragmentu bez wpływania na cykl życia fragmentu.

Nie musisz używać transakcji fragmentu, aby przełączać widoczność widoków w fragmentach, ale te metody są przydatne w przypadkach, gdy chcesz, aby zmiany stanu widoczności były powiązane z transakcjami w dolnej części stosu.

Podłączanie i odłączanie fragmentów

Metoda FragmentTransaction detach() odłącza fragment od interfejsu, niszcząc jego hierarchię widoku. Fragment pozostaje w tym samym stanie (STOPPED) co po umieszczeniu na stosu z tyłu. Oznacza to, że fragment został usunięty z interfejsu, ale nadal jest zarządzany przez menedżera fragmentów.

Metoda attach() ponownie przyłącza fragment, z którego został wcześniej odłączony. Powoduje to odtworzenie hierarchii widoku, dołączenie jej do interfejsu użytkownika i wyświetlenie.

Ponieważ FragmentTransaction jest traktowany jako pojedynczy nierozerwalny zestaw operacji, wywołania detachattach w ramach tej samej transakcji skutecznie się wzajemnie anulują, co pozwala uniknąć zniszczenia i natychmiastowego odtworzenia interfejsu fragmentu. Jeśli chcesz odłączyć fragment, a następnie natychmiast go ponownie dołączyć, użyj oddzielnych transakcji rozdzielonych znakiem executePendingOperations() (jeśli używasz znaku commit()).

.