Trong thời gian chạy, FragmentManager
có thể thêm, xoá, thay thế và thực hiện các thao tác khác với các mảnh (fragment) để phản hồi khi người dùng tương tác. Mỗi tập hợp thay đổi mảnh mà bạn xác nhận (commit) được gọi là một giao dịch (transaction) và bạn có thể chỉ định việc cần làm bên trong giao dịch bằng cách sử dụng các API mà lớp FragmentTransaction
cung cấp. Bạn có thể nhóm nhiều hành động (action) thành một giao dịch duy nhất, ví dụ: một giao dịch có thể thêm hoặc thay thế nhiều mảnh. Thao tác nhóm này có thể hữu ích khi bạn hiển thị nhiều mảnh đồng cấp trên cùng một màn hình, chẳng hạn như với chế độ xem phân tách.
Bạn có thể lưu từng giao dịch vào ngăn xếp lui do FragmentManager
quản lý, cho phép người dùng di chuyển trở lại thông qua các thay đổi mảnh – tương tự như việc di chuyển ngược qua các hoạt động.
Bạn có thể nhận bản sao của FragmentTransaction
từ FragmentManager
bằng cách gọi beginTransaction()
, như trong ví dụ sau:
Kotlin
val fragmentManager = ... val fragmentTransaction = fragmentManager.beginTransaction()
Java
FragmentManager fragmentManager = ... FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Lệnh gọi cuối cùng trên mỗi FragmentTransaction
phải xác nhận giao dịch.
Lệnh gọi commit()
báo hiệu cho FragmentManager
rằng tất cả thao tác (operation) đã được thêm vào giao dịch.
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();
Cho phép sắp xếp lại các thay đổi về trạng thái mảnh
Mỗi FragmentTransaction
sẽ sử dụng setReorderingAllowed(true)
:
Kotlin
supportFragmentManager.commit { ... setReorderingAllowed(true) }
Java
FragmentManager fragmentManager = ... fragmentManager.beginTransaction() ... .setReorderingAllowed(true) .commit();
Để tương thích với hành vi, cờ sắp xếp lại không được bật theo mặc định.
Tuy nhiên, bạn cần phải cho phép FragmentManager
thực thi FragmentTransaction
đúng cách, đặc biệt là khi ứng dụng này hoạt động trên ngăn xếp lui cũng như chạy ảnh động và hiệu ứng chuyển đổi. Việc bật cờ sẽ đảm bảo rằng nếu nhiều giao dịch được thực hiện cùng nhau, thì mọi mảnh trung gian (tức là các giao dịch được thêm vào và thay thế ngay lập tức) sẽ không trải qua các thay đổi trong vòng đời hoặc ảnh động/hiệu ứng chuyển tiếp sẽ được thực thi. Lưu ý rằng cờ này ảnh hưởng đến cả quá trình thực hiện giao dịch ban đầu lẫn việc đảo ngược giao dịch bằng popBackStack()
.
Thêm và xoá mảnh
Để thêm một mảnh vào FragmentManager
, hãy gọi add()
trên giao dịch. Phương thức này sẽ nhận được mã nhận dạng của vùng chứa (container) cho mảnh, cũng như tên lớp của mảnh bạn muốn thêm. Mảnh đã thêm sẽ được chuyển sang trạng thái RESUMED
. Chúng tôi rất khuyến khích việc vùng chứa là một FragmentContainerView
– một phần của hệ phân cấp thành phần hiển thị.
Để xoá một mảnh khỏi máy chủ lưu trữ, hãy gọi remove()
, truyền vào thực thể mảnh được truy xuất từ trình quản lý mảnh thông qua findFragmentById()
hoặc findFragmentByTag()
.
Nếu thành phần hiển thị của mảnh trước đây đã được thêm vào vùng chứa, thì thành phần hiển thị đó sẽ bị xoá khỏi vùng chứa tại thời điểm này. Mảnh bị xoá sẽ được chuyển sang trạng thái DESTROYED
.
Hãy sử dụng replace()
để thay thế một mảnh hiện có trong vùng chứa bằng một thực thể của lớp mảnh mới mà bạn cung cấp. Việc gọi replace()
tương đương với việc gọi remove()
bằng một mảnh trong vùng chứa và thêm một mảnh mới vào chính vùng chứa đó.
Đoạn mã sau đây cho biết cách bạn có thể thay thế một mảnh bằng một mảnh khác:
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();
Trong ví dụ này, một bản sao mới của ExampleFragment
thay thế mảnh (nếu có) hiện có trong vùng chứa bố cục được xác định bởi R.id.fragment_container
.
Theo mặc định, các thay đổi đã thực hiện trong FragmentTransaction
sẽ không được thêm vào ngăn xếp lui. Để lưu các thay đổi đó, bạn có thể gọi addToBackStack()
trên FragmentTransaction
. Để biết thêm thông tin, hãy xem Trình quản lý mảnh.
Xác nhận (commit) không đồng bộ
Việc gọi commit()
sẽ không thực hiện giao dịch ngay lập tức. Thay vào đó, giao dịch được lên lịch để chạy trên chuỗi giao diện người dùng chính ngay khi có thể thực hiện. Tuy nhiên, nếu cần, bạn có thể gọi commitNow()
để chạy giao dịch mảnh trên luồng giao diện người dùng (UI thread) ngay lập tức.
Xin lưu ý rằng commitNow
không tương thích với addToBackStack
. Ngoài ra, bạn có thể thực thi tất cả FragmentTransactions
đang chờ xử lý do các lệnh gọi commit()
chưa chạy gửi bằng cách gọi executePendingTransactions()
. Phương pháp này tương thích với addToBackStack
.
Đối với phần lớn trường hợp sử dụng, bạn chỉ cần duy nhất commit()
.
Thứ tự hoạt động rất quan trọng
Thứ tự bạn thực hiện các thao tác trong FragmentTransaction
là rất quan trọng, đặc biệt là khi sử dụng setCustomAnimations()
. Phương thức này áp dụng ảnh động nhất định cho tất cả thao tác mảnh theo sau.
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()
Giới hạn vòng đời của mảnh
FragmentTransactions
có thể ảnh hưởng đến trạng thái vòng đời của các mảnh riêng lẻ được thêm trong phạm vi giao dịch. Khi tạo FragmentTransaction
, setMaxLifecycle()
sẽ đặt trạng thái tối đa cho mảnh đã cho. Ví dụ: ViewPager2
sử dụng setMaxLifecycle()
để giới hạn các mảnh ngoài màn hình ở trạng thái STARTED
.
Hiện và ẩn thành phần hiển thị của mảnh
Sử dụng các phương thức FragmentTransaction
, show()
và hide()
để hiện và ẩn thành phần hiển thị của các mảnh đã được thêm vào vùng chứa.
Các phương thức này thiết lập chế độ hiển thị của các thành phần hiển thị của mảnh mà không ảnh hưởng đến vòng đời của mảnh.
Mặc dù bạn không cần phải sử dụng giao dịch mảnh để chuyển đổi chế độ hiển thị của các thành phần hiển thị trong một mảnh, nhưng các phương pháp này hữu ích đối với trường hợp bạn muốn thay đổi trạng thái hiển thị liên kết với các giao dịch trong ngăn xếp lui.
Đính kèm và tách rời mảnh
Phương thức FragmentTransaction
detach()
sẽ tách rời mảnh khỏi giao diện người dùng và huỷ bỏ thứ bậc của hệ phân cấp thành phần hiển thị. Mảnh này còn nguyên trạng thái (STOPPED
) như khi được đặt vào ngăn xếp lui.
Tức là mảnh đã bị xoá khỏi giao diện người dùng nhưng vẫn do trình quản lý mảnh quản lý.
Phương thức attach()
sẽ đính kèm lại một đoạn trước đó từng bị tách rời ra.
Điều này khiến hệ phân cấp thành phần hiển thị được tạo lại, đính kèm với giao diện người dùng và hiển thị.
Vì FragmentTransaction
được coi là một tập hợp các thao tác atom đơn, nên các lệnh gọi đến detach
và attach
trên cùng một thực thể mảnh trong cùng một giao dịch sẽ huỷ liên kết với nhau một cách triệt để, do đó, tránh việc phá huỷ và tái tạo ngay lập tức trên giao diện người dùng của mảnh. Hãy sử dụng các giao dịch riêng biệt, phân tách nhau bằng executePendingOperations()
khi sử dụng commit()
, nếu bạn muốn tách rời rồi sau đó đính kèm lại một mảnh.