Hiểu về setRetainInstance (boolean) của Fragment


341

Bắt đầu với tài liệu:

công khai void setRetainInstance (boolean giữ lại)

Kiểm soát xem một phiên bản phân đoạn có được giữ lại trong quá trình tạo lại Hoạt động hay không (chẳng hạn như từ thay đổi cấu hình). Điều này chỉ có thể được sử dụng với các mảnh không nằm trong ngăn xếp phía sau. Nếu được đặt, vòng đời của đoạn sẽ hơi khác khi hoạt động được tạo lại:

  • onDestroy () sẽ không được gọi (nhưng onDetach () vẫn sẽ như vậy, vì đoạn này đang bị tách ra khỏi hoạt động hiện tại của nó).
  • onCreate (Bundle) sẽ không được gọi vì đoạn này không được tạo lại.
  • onAttach (Hoạt động) và onActivityCreated (Gói) vẫn sẽ được gọi.

Tôi có một số câu hỏi:

  • Liệu đoạn này cũng giữ được quan điểm của nó, hay điều này sẽ được tạo lại khi thay đổi cấu hình? Chính xác thì "giữ lại" nghĩa là gì?

  • Mảnh vỡ sẽ bị phá hủy khi người dùng rời khỏi hoạt động?

  • Tại sao nó không hoạt động với các mảnh trên ngăn xếp phía sau?

  • Đó là những trường hợp sử dụng mà nó có ý nghĩa để sử dụng phương pháp này?


Câu trả lời:


348

Trước hết, hãy xem bài viết của tôi về các mảnh vỡ được giữ lại. Nó sẽ giúp.

Bây giờ để trả lời câu hỏi của bạn:

Liệu đoạn này cũng giữ trạng thái xem của nó , hay điều này sẽ được tạo lại khi thay đổi cấu hình - chính xác thì "được giữ lại" là gì?

Có, Fragmenttrạng thái sẽ được giữ lại trong suốt quá trình thay đổi cấu hình. Cụ thể, "giữ lại" có nghĩa là đoạn đó sẽ không bị hủy khi thay đổi cấu hình. Đó là, cái Fragmentsẽ được giữ lại ngay cả khi thay đổi cấu hình làm cho phần bên dưới Activitybị phá hủy.

Mảnh vỡ sẽ bị phá hủy khi người dùng rời khỏi hoạt động?

Cũng giống như Activitys, Fragments có thể bị hệ thống phá hủy khi tài nguyên bộ nhớ thấp. Việc bạn có phân đoạn giữ trạng thái cá thể của chúng qua các thay đổi cấu hình hay không sẽ không ảnh hưởng đến việc hệ thống có phá hủy Fragments hay không khi bạn rời khỏi Activity. Nếu bạn rời khỏi Activity(tức là bằng cách nhấn nút home), Fragments có thể hoặc không bị phá hủy. Nếu bạn rời khỏi Activitybằng cách nhấn nút quay lại (do đó, gọi finish()và hủy hiệu quả Activity), tất cả các Activitys đính kèm Fragmentcũng sẽ bị hủy.

Tại sao nó không hoạt động với các mảnh trên ngăn xếp phía sau?

Có thể có nhiều lý do tại sao nó không được hỗ trợ, nhưng lý do rõ ràng nhất đối với tôi là việc Activitygiữ một tham chiếu đến FragmentManagerFragmentManagerquản lý backstack. Đó là, bất kể bạn có chọn giữ lại Fragments của mình hay không, Activity(và do đó FragmentManager, backstack) sẽ bị hủy khi thay đổi cấu hình. Một lý do khác tại sao nó có thể không hoạt động là bởi vì mọi thứ có thể trở nên khó khăn nếu cả hai mảnh được giữ lại mảnh không giữ lại được phép tồn tại trên cùng một backstack.

Đó là những trường hợp sử dụng mà nó có ý nghĩa để sử dụng phương pháp này?

Các đoạn được giữ lại có thể khá hữu ích để truyền bá thông tin trạng thái - đặc biệt là quản lý luồng - qua các trường hợp hoạt động. Ví dụ, một đoạn có thể phục vụ như một máy chủ cho một ví dụ Threadhoặc AsyncTask, quản lý hoạt động của nó. Xem bài viết trên blog của tôi về chủ đề này để biết thêm thông tin.

Nói chung, tôi sẽ coi nó tương tự như việc sử dụng onConfigurationChangedvới một Activity... không sử dụng nó như một chiếc băng đô chỉ vì bạn quá lười biếng để thực hiện / xử lý một sự thay đổi định hướng một cách chính xác. Chỉ sử dụng nó khi bạn cần.


37
Xem các đối tượng không được giữ lại, chúng luôn bị phá hủy khi thay đổi cấu hình.
Markus Junginger

103
Theo như tôi có thể nói, nếu bạn có setRetainInstance(true), Fragmentđối tượng java và tất cả nội dung của nó không bị phá hủy khi xoay, nhưng khung nhìn được tạo lại. Điều đó được onCreatedView()gọi là một lần nữa. Về cơ bản, đó là cách nó nên hoạt động với ActivitiesAndroid 1.0. Tôi không nghĩ rằng nó là "lười biếng" để sử dụng nó, hoặc sử dụng nó không "phù hợp". Trong thực tế, tôi không thể hiểu tại sao nó không phải là mặc định hoặc tại sao bạn lại muốn tắt nó.
Timmmm

24
Tôi tìm thấy lời giải thích của bạn cho "Tại sao nó không hoạt động với các mảnh trên ngăn xếp phía sau?" khó để hiểu. Nhưng có lẽ tôi ngu ngốc :(
HGPB

13
@dierre Một hoạt động có thể bị phá hủy theo nhiều cách. Ví dụ: nếu bạn nhấp vào "quay lại", hoạt động sẽ bị hủy. Nếu bạn nhấp vào "nhà", hoạt động sẽ bị dừng và một lúc nào đó trong tương lai có thể bị hủy khi bộ nhớ thấp. Các Fragments được giữ lại chỉ được giữ lại qua các thay đổi cấu hình, trong đó hoạt động cơ bản sẽ bị hủy và được tạo lại ngay lập tức. Trong tất cả các trường hợp khác trong đó hoạt động bị phá hủy, các mảnh được giữ lại cũng sẽ bị phá hủy.
Alex Lockwood

3
@AlexLockwood bạn có thể vui lòng xác nhận những điều sau: Mặc dù đã setRetainInstance(true)được sử dụng, người ta vẫn phải thực hiện sự kiên trì của chính họ ( savedInstanceStatehoặc nếu không) để có thể xử lý tất cả các tình huống: ví dụ: "phím home, xoay, quay lại ứng dụng" tạo lại đoạn của tôi với hàm tạo gọi, mất tất cả các biến trạng thái. Tôi có một AsyncTaskbiến là thành viên, đó là lý do tại sao tôi muốn giữ lại, bây giờ, nếu tôi muốn nó hoạt động, tôi buộc phải dừng nhiệm vụ, lưu trạng thái và tiếp tục khi người dùng quay lại. Vì vậy, tất cả trong tất cả, đây chỉ là một cách nhanh chóng để giúp xoay vòng, nhưng nói chung là vô dụng.
TWiStErRob

28

setRetaininstancechỉ hữu ích khi bạn activitybị hủy và được tạo lại do thay đổi cấu hình vì các phiên bản được lưu trong khi gọi đến onRetainNonConfigurationInstance. Đó là, nếu bạn xoay thiết bị, các mảnh được giữ lại sẽ vẫn ở đó (chúng không bị phá hủy và được tạo lại.) Nhưng khi thời gian chạy giết chết hoạt động để lấy lại tài nguyên, không còn gì cả. Khi bạn nhấn nút quay lại và thoát khỏi hoạt động, mọi thứ sẽ bị phá hủy.

Thông thường tôi sử dụng chức năng này để lưu định hướng thay đổi Thời gian. Tôi đã tải xuống một loạt Bitmap từ máy chủ và mỗi bit là 1MB, khi người dùng vô tình xoay thiết bị của mình, tôi chắc chắn không muốn thực hiện lại tất cả công việc tải xuống. Tôi tạo một Fragmentbitmap giữ và thêm nó vào trình quản lý và gọi setRetainInstance, tất cả các Bitmap vẫn ở đó ngay cả khi hướng màn hình thay đổi.


Bạn có tạo các đoạn "Chỉ dữ liệu" (không có bất kỳ tiện ích nào) giống như một người giữ cho bạn bitmap hay các đoạn đó cũng có thể có các widget không? Tôi đã đọc một cái gì đó về sự nguy hiểm của việc rò rỉ bộ nhớ khi đoạn chứa nội dung liên quan đến bối cảnh / Hoạt động ...
hgoebl

Khung sẽ xóa mActivitytài liệu tham khảo cho bạn. Nhưng tôi không biết liệu thời gian chạy cũng sẽ xóa các widget trong trường hợp phân đoạn trong trường hợp này. Vui lòng thử hoặc đi sâu vào mã nguồn.
suitianshi

Một ví dụ hay về thời điểm chúng ta có thể sử dụng setRetaininstance
Mu Sa

12

SetRetainInstance (true) cho phép phân loại tồn tại. Các thành viên của nó sẽ được giữ lại trong quá trình thay đổi cấu hình như xoay vòng. Nhưng nó vẫn có thể bị giết khi hoạt động bị giết trong nền. Nếu hoạt động chứa trong nền bị hệ thống tiêu diệt, thì instanceState sẽ được lưu bởi hệ thống mà bạn đã xử lý đúng cách trênSaveInstanceState. Nói cách khác, onSaveInstanceState sẽ luôn được gọi. Mặc dù onCreateView sẽ không được gọi nếu SetRetainInstance là đúng và đoạn / hoạt động chưa bị giết, nó vẫn sẽ được gọi nếu nó bị giết và được đưa trở lại.

Dưới đây là một số phân tích về hoạt động / đoạn Android hy vọng nó sẽ giúp. http://ideaventure.blogspot.com.au/2014/01/android-activityfragment-life- Motorcycle.html


7
Tôi chắc chắn thấy onCreateView được gọi lại trên đoạn bị giữ lại khi xoay màn hình.
aij

Đây có phải là liên kết blog của riêng bạn? Bạn nên làm rõ nếu đó là trường hợp.
Flexo

4

setRetainInstance () - Không dùng nữa

Như phiên bản mảnh 1.3.0-alpha01

Phương thức setRetainInstance () trên Fragment đã không được chấp nhận. Với việc giới thiệu ViewModels, các nhà phát triển có một API cụ thể để duy trì trạng thái có thể được liên kết với các biểu đồ Hoạt động, Đoạn và Điều hướng. Điều này cho phép các nhà phát triển sử dụng một mảnh bình thường, không bị giữ lại và giữ trạng thái cụ thể mà họ muốn giữ riêng, tránh một nguồn rò rỉ chung trong khi duy trì các thuộc tính hữu ích của một lần tạo và hủy trạng thái giữ lại (cụ thể là hàm tạo của ViewModel và cuộc gọi lại onCleared () mà nó nhận được).


2

setRetainInstance (boolean) rất hữu ích khi bạn muốn có một số thành phần không gắn với vòng đời Activity. Kỹ thuật này được rxloader sử dụng ví dụ để "xử lý vòng đời hoạt động của Android cho rxjava's Observable" (mà tôi đã tìm thấy ở đây ).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.