Mỗi phiên bản Fragment
đều có vòng đời riêng. Khi một người dùng điều hướng và tương tác với ứng dụng, các phân mảnh sẽ dịch chuyển qua các trạng thái khác nhau của vòng đời khi chúng được thêm, xoá, xuất hiện hoặc thoát khỏi màn hình.
Để quản lý vòng đời, Fragment
thực hiện LifecycleOwner
, hiển thị một đối tượng Lifecycle
có thể được truy cập bằng phương thức getLifecycle()
.
Mỗi trạng thái Lifecycle
sẽ được biểu thị trong enum Lifecycle.State
.
Khi thiết lập Fragment
trên Lifecycle
, bạn có thể sử dụng các kỹ thuật và lớp có sẵn để Điều khiển vòng đời bằng các thành phần nhận biết vòng đời.
Ví dụ: bạn có thể hiển thị vị trí của thiết bị trên màn hình bằng cách sử dụng một thành phần nhận biết vòng đời. Thành phần này có khả năng tự động bắt đầu lắng nghe khi phân mảnh được kích hoạt và dừng lại khi phân mảnh chuyển sang trạng thái không hoạt động.
Thay vì sử dụng LifecycleObserver
, lớp Fragment
chứa các phương thức gọi lại tương ứng với từng thay đổi trong vòng đời của một phân mảnh. Các phương thức này bao gồm onCreate()
, onStart()
, onResume()
,onPause()
, onStop()
và onDestroy()
.
Giao diện của phân mảnh có Lifecycle
riêng biệt được quản lý độc lập với Lifecycle
của phân mảnh. Các phân mảnh duy trì một LifecycleOwner
cho giao diện của mình, có thể được truy cập bằng getViewLifecycleOwner()
hoặc getViewLifecycleOwnerLiveData()
Quyền truy cập vào Lifecycle
của giao diện sẽ cần thiết trong trường hợp một thành phần nhận biết vòng đời chỉ hoạt động khi tồn tại một giao diện của phân mảnh, chẳng hạn như quan sát LiveData
chỉ nhằm mục đích hiển thị trên màn hình.
Chủ đề này sẽ bàn chi tiết về vòng đời của Fragment
, giải thích một số quy tắc xác định trạng thái vòng đời của phân mảnh và chỉ ra mối quan hệ giữa các trạng thái Lifecycle
và các lệnh gọi lại trong vòng đời của phân mảnh.
Các phân mảnh và trình quản lý phân mảnh
Khi một phân mảnh được sao chép, nó sẽ bắt đầu ở trạng thái INITIALIZED
. Để dịch chuyển trong phần còn lại của vòng đời, phân mảnh phải được đưa vào một FragmentManager
. FragmentManager
có trách nhiệm xác định trạng thái của phân mảnh và chuyển chúng sang trạng thái đó.
Ngoài vòng đời phân mảnh, FragmentManager
còn có trách nhiệm đính kèm các phân mảnh vào hoạt động của máy chủ và tách chúng ra khi phân mảnh không còn được sử dụng. Lớp Fragment
có hai phương thức gọi lại là onAttach()
và onDetach()
có thể được ghi đè để sử dụng khi một trong hai hoạt động này diễn ra.
Lệnh gọi lại onAttach()
được bật khi phân mảnh đã được thêm vào FragmentManager
và được đính kèm vào hoạt động của máy chủ. Tại thời điểm này, phân mảnh đang hoạt động và FragmentManager
đang quản lý trạng thái vòng đời của nó. Khi đó, các phương thức FragmentManager
như findFragmentById()
sẽ trả phân mảnh này về lại.
onAttach()
luôn được gọi trước khi diễn ra mọi sự thay đổi trạng thái vòng đời.
Lệnh gọi lại onDetach()
được bật khi phân mảnh đã bị xoá khỏi FragmentManager
và được tách khỏi hoạt động của máy chủ. Phân mảnh ngừng hoạt động và không thể truy xuất bằng findFragmentById()
nữa.
onDetach()
luôn được gọi sau khi diễn ra mọi sự thay đổi trạng thái vòng đời.
Lưu ý rằng các lệnh gọi lại này không liên quan đến các phương thức FragmentTransaction
attach()
và detach()
.
Để biết thêm thông tin về các phương thức này, hãy xem Giao dịch phân mảnh.
Các trạng thái vòng đời của mảnh và lệnh gọi lại
Khi xác định trạng thái vòng đời của phân mảnh, FragmentManager
sẽ xem xét các điểm sau:
- Trạng thái cực đại của phân mảnh được xác định theo
FragmentManager
của nó. Phân mảnh không thể hoạt động vượt quá trạng thái củaFragmentManager
của nó. - Là một chức năng của
FragmentTransaction
, bạn có thể thiết lập trạng thái vòng đời cực đại cho phân mảnh bằng cách sử dụngsetMaxLifecycle()
. - Trạng thái vòng đời của phân mảnh không bao giờ được lớn hơn trạng thái gốc. Ví dụ: một phân mảnh gốc hay một hoạt động gốc phải được khởi động trước các phân mảnh con của chúng. Tương tự, các phân mảnh con phải được dừng lại trước phân mảnh gốc hay hoạt động gốc.
Hình 1 cho thấy từng trạng thái Lifecycle
của mảnh và mối liên hệ giữa chúng với phương thức gọi lại trong vòng đời của mảnh và thành phần hiển thị Lifecycle
của mảnh.
Khi phân mảnh hoạt động trong suốt vòng đời của mình, nó sẽ dịch chuyển lên và xuống qua các trạng thái. Ví dụ: một phân mảnh được xếp vào phần trên cùng của back stack sẽ dịch chuyển theo hướng đi lên từ CREATED
đến STARTED
đến RESUMED
. Ngược lại, khi một phân mảnh bị bật ra khỏi back stack, nó sẽ dịch chuyển theo hướng đi xuống qua các trạng thái đó, từ RESUMED
đến STARTED
đến CREATED
và cuối cùng là DESTROYED
.
Dịch chuyển trạng thái đi lên
Khi dịch chuyển đi lên qua các trạng thái vòng đời, trước tiên, phân mảnh sẽ thực hiện lệnh gọi lại vòng đời liên kết với trạng thái mới của mình. Sau khi lệnh gọi lại này hoàn tất, Lifecycle.Event
liên quan sẽ được phát cho người quan sát bởi Lifecycle
của phân mảnh, tiếp theo là Lifecycle
của giao diện nếu đã được sao chép.
Phân mảnh ĐƯỢC TẠO
Khi phân mảnh đạt đến trạng thái CREATED
, nó đã được thêm vào FragmentManager
và phương thức onAttach()
đã được gọi.
Đây là lúc thích hợp để khôi phục mọi trạng thái đã lưu liên kết với chính phân mảnh đó thông qua SavedStateRegistry
của phân mảnh.
Lưu ý lúc này giao diện của phân mảnh vẫn chưa được tạo và mọi trạng thái liên kết với giao diện của phân mảnh chỉ được khôi phục sau khi giao diện đã được tạo.
Quá trình dịch chuyển này sẽ kích hoạt lệnh onCreate()
. Lệnh gọi lại này cũng nhận được một đối số savedInstanceState
Bundle
chứa mọi trạng thái đã được onSaveInstanceState()
lưu trước đó.
Lưu ý savedInstanceState
có giá trị null
vào lần đầu tiên tạo mảnh, nhưng giá trị này luôn khác rỗng trong các lần tái tạo tiếp theo, ngay cả khi không ghi đè onSaveInstanceState()
. Hãy xem phần Lưu trạng thái với các phân mảnh để biết thêm chi tiết.
Phân mảnh ĐƯỢC TẠO và Chế độ xem ĐƯỢC KHỞI CHẠY
Lifecycle
của giao diện của phân mảnh chỉ được tạo khi Fragment
cung cấp một phiên bản View
hợp lệ. Trong hầu hết trường hợp, có thể sử dụng Hàm tạo phân mảnh để lấy @LayoutId
với chức năng tự động phóng to giao diện tại thời điểm thích hợp. Cũng có thể ghi đè onCreateView()
để tự động phóng to hoặc tạo giao diện của phân mảnh.
Chỉ khi giao diện của phân mảnh được sao chép với một View
không phải là null (khuyết), View
đó sẽ được thiết lập trên phân mảnh và có thể được truy xuất bằng getView()
. Sau đó, getViewLifecycleOwnerLiveData()
sẽ được cập nhật bằng INITIALIZED
LifecycleOwner
mới, tương ứng với giao diện của phân mảnh. Lệnh gọi lại onViewCreated()
cũng được gọi tại thời điểm này.
Đây là lúc thích hợp để thiết lập trạng thái ban đầu của giao diện, nhằm bắt đầu quan sát các phiên bản LiveData
với lệnh gọi lại có chức năng cập nhật giao diện của phân mảnh và để thiết lập bộ chuyển đổi trên mọi phiên bản RecyclerView
hoặc ViewPager2
trong giao diện của phân mảnh.
Phân mảnh và Chế độ xem ĐƯỢC TẠO
Sau khi giao diện của phân mảnh đã được tạo, trạng thái trước đó (nếu có) của giao diện sẽ được khôi phục, và Lifecycle
của giao diện sẽ được chuyển sang trạng thái CREATED
. Chủ sở hữu vòng đời của giao diện cũng sẽ phát ON_CREATE
cho người quan sát. Ở đây, bạn nên khôi phục mọi trạng thái bổ sung liên kết với giao diện của phân mảnh.
Quá trình chuyển đổi này cũng bật lệnh gọi lại onViewStateRestored()
.
Phân mảnh và Chế độ xem ĐƯỢC BẮT ĐẦU
Cần liên kết các thành phần nhận biết vòng đời với trạng thái STARTED
của phân mảnh, vì trạng thái này sẽ đảm bảo giao diện của phân mảnh có sẵn nếu đã được tạo và có thể thực hiện FragmentTransaction
an toàn trên phần tử con FragmentManager
của phân mảnh. Nếu giao diện của phân mảnh không phải là giá trị null, Lifecycle
của giao diện sẽ được chuyển đến STARTED
ngay sau Lifecycle
của phân mảnh được chuyển đến STARTED
.
Khi phân mảnh ở trạng thái STARTED
, lệnh gọi lại onStart()
sẽ được bật lên.
Phân mảnh và Chế độ xem ĐƯỢC TIẾP TỤC
Khi phân mảnh ở chế độ hiển thị, tất cả các hiệu ứng Animator
và Transition
đã hoàn tất và phân mảnh đã sẵn sàng cho tương tác của người dùng. Lifecycle
của phân mảnh chuyển sang trạng thái RESUMED
và lệnh gọi lại onResume()
sẽ được bật lên.
Việc chuyển sang RESUMED
là một tín hiệu tin cậy cho thấy người dùng lúc này có thể tương tác với phân mảnh. Những phân mảnh không phải là RESUMED
không được thiết lập tiêu điểm trên giao diện theo cách thủ công hoặc thử điều khiển chế độ hiển thị phương thức nhập.
Dịch chuyển trạng thái xuống dưới
Khi một phân mảnh dịch chuyển xuống trạng thái vòng đời thấp hơn, Lifecycle.Event
liên quan sẽ được phát cho người quan sát bởi Lifecycle
của giao diện nếu được sao chép, tiếp đến là Lifecycle
của phân mảnh. Sau khi sự kiện vòng đời của phân mảnh được phát, phân mảnh sẽ gọi lệnh gọi lại vòng đời liên kết.
Phân mảnh và Chế độ xem ĐƯỢC BẮT ĐẦU
Khi người dùng bắt đầu rời khỏi phân mảnh, và trong khi phân mảnh đó vẫn còn hiển thị, Lifecycle
của phân mảnh và giao diện của nó được chuyển trở lại trạng thái STARTED
và phát ON_PAUSE
cho người quan sát. Sau đó, phân mảnh sẽ bật lệnh gọi lại onPause()
.
Phân mảnh và Chế độ xem ĐƯỢC TẠO
Khi phân mảnh không còn hiển thị, các Lifecycle
của phân mảnh và giao diện của phân mảnh sẽ được chuyển sang trạng thái CREATED
và phát ON_STOP
cho người quan sát. Quá trình chuyển đổi trạng thái này diễn ra không chỉ do hoạt động gốc hay phân mảnh gốc bị ngừng hoạt động mà còn do việc lưu trạng thái của hoạt động gốc hay phân mảnh gốc. Việc này đảm bảo ON_STOP
sẽ được bật trước khi lưu trạng thái của phân mảnh. Nhờ đó, ON_STOP
trở thành điểm cuối cùng an toàn để thực hiện FragmentTransaction
trên phần tử con FragmentManager
.
Như minh hoạ trên hình 2, thứ tự của lệnh gọi lại onStop()
và quá trình lưu trạng thái với onSaveInstanceState()
còn tuỳ theo cấp độ API. Đối với tất cả các cấp độ API trước API 28, onSaveInstanceState()
sẽ được gọi trước onStop()
.
Đối với API cấp 28 trở lên, thứ tự gọi được đảo ngược.
Phân mảnh ĐƯỢC TẠO và Chế độ xem BỊ HUỶ BỎ
Sau khi tất cả ảnh động và quá trình chuyển đổi của giai đoạn kết thúc đã hoàn tất và giao diện của phân mảnh đã được tách khỏi cửa sổ, Lifecycle
của giao diện sẽ được chuyển vào trạng thái DESTROYED
và phát ON_DESTROY
cho người quan sát. Sau đó, phân mảnh sẽ bật lệnh gọi lại onDestroyView()
. Lúc này, giao diện của phân mảnh đã kết thúc vòng đời và getViewLifecycleOwnerLiveData()
trả về giá trị null
.
Khi đó, tất cả các tham chiếu đến giao diện của phân mảnh phải được xoá, cho phép giao diện của phân mảnh được đưa vào thùng rác.
Phân mảnh BỊ HUỶ BỎ
Nếu mảnh bị xoá hoặc nếu FragmentManager
bị huỷ bỏ, Lifecycle
của mảnh sẽ được chuyển sang trạng thái DESTROYED
và gửi sự kiện ON_DESTROY
cho trình quan sát. Sau đó, phân mảnh sẽ bật lệnh gọi lại onDestroy()
. Tại thời điểm này, phân mảnh này kết thúc vòng đời của mình.
Tài nguyên khác
Để biết thêm thông tin liên quan đến vòng đời của phân mảnh, hãy xem các tài nguyên bổ sung sau.