2013-05-23 31 views
7

Tôi muốn sử dụng WeakReference s như một phần của bộ nhớ cache bitmap (android) để có thể kiểm tra khi bitmap không được sử dụng nữa.Khi nào WeakReference # get() bắt đầu trả về null?

Bộ nhớ cache của tôi có kích thước tối đa nhỏ hơn không gian heap Java. Khi một bitmap mới sẽ tràn bộ nhớ cache, nó sẽ cho phép các bitmap không cần nữa.

Câu hỏi của tôi: Khi nào phương thức get() của một WeakReference trả về null?

  1. Ngay sau khi không có tham chiếu mạnh mẽ hơn cho đối tượng? (và GC chưa xảy ra)
  2. Hoặc khi GC đã chạy và xác định rằng chúng không có tham chiếu mạnh mẽ hơn đối với đối tượng?

Nếu 2. đúng hơn là tôi có thể gặp tình huống mà bộ nhớ cache của tôi có thể lấp đầy và GC gần đây không chạy vì lý do nào đó.

Sau đó, ngay cả khi tôi đã từ bỏ tham chiếu SAU lần chạy GC cuối cùng, WeakReference#get() vẫn sẽ trả lại đối tượng và bộ nhớ cache của tôi sẽ không xóa nó.

Trả lời

10

Câu trả lời là tùy thuộc vào phiên bản Android bạn đang sử dụng. Một nơi nào đó trong khung thời gian 2,3, Android đã thay đổi cách xử lý hoặc tham chiếu yếu. Trước đây, nó đã xóa chúng khi GC chạy. Kể từ một số phiên bản 2.3 (2.3.3?) Nó bắt đầu xóa chúng ngay lập tức khi tham chiếu mạnh cuối cùng biến mất. Vì vậy, trong các phiên bản hiện đại của Android, các tham chiếu yếu là vô dụng.

Trước thay đổi này, các tham chiếu yếu được sử dụng để lưu vào bộ nhớ đệm. Chúng không còn hoạt động nữa. Cách chính xác bây giờ là sử dụng một LRUCache. Nếu bạn cần hỗ trợ các phiên bản cũ hơn, hãy sử dụng thư viện hỗ trợ để backport bộ nhớ cache LRU.

Sau khi tìm kiếm, tôi nghĩ rằng thay đổi được thực hiện trong 3.0, chứ không phải 2.3. Tuy nhiên, giải pháp là như nhau.

+0

Tham chiếu mềm được dành cho bộ nhớ đệm. Hành vi của họ trên Android là gì? –

+2

Giống nhau, chúng được giải phóng ngay khi không có tham chiếu mạnh mẽ nào tồn tại. Mà sau chữ cái của tiêu chuẩn Java, nếu không phải là tinh thần. –

+0

Thay đổi ở cấp API 9. Tài liệu liên quan: http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html#memory-cache – Delyan

5

WeakReference được xóa ngay sau khi GC xác định rằng đối tượng có thể truy cập yếu.

Điều này gần với trường hợp thứ hai của bạn. Tuy nhiên, khả năng tiếp cận yếu không chỉ đòi hỏi sự vắng mặt của các tài liệu tham khảo mạnh mẽ, mà còn thiếu sự tham khảo mềm.

Từ các tài liệu gói Java cho java.lang.ref:

tài liệu tham khảo mềm và yếu sẽ được tự động xóa bởi các nhà sưu tập trước khi được bổ sung vào hàng đợi mà họ đã được đăng ký, nếu có.

...

Một đối tượng là một cách yếu ớt có thể truy cập nếu nó không phải là mạnh mẽ hay nhẹ nhàng có thể truy cập nhưng có thể đạt được bằng cách đi qua một tham chiếu yếu. Khi các tham chiếu yếu tới một đối tượng yếu có thể truy cập được xóa, đối tượng sẽ đủ điều kiện để hoàn thành.

+1

Đây là chính xác từ quan điểm Java, nhưng không phải toàn bộ câu chuyện cho Android. Xem bài đăng của tôi về cách Android triển khai những tính năng này cụ thể và cách nó thay đổi trong quá khứ. –

4

Để bộ nhớ cache bitmap sử dụng SoftReference thay vì yếu. GC sẽ xóa WeakReference ngay sau khi nó mất tất cả các tham chiếu mạnh mẽ và mềm của nó mà có thể phá hủy mục đích của bộ nhớ đệm. SoftReference chỉ được xóa nếu có bộ nhớ thấp. Và nó được đảm bảo rằng GC sẽ được chạy trước khi ném một OOME.

+0

+1 - Tôi nên nghĩ đến việc nhắc đến điều đó, sau khi phải thay thế các tham chiếu yếu trong toàn bộ thư viện với phần mềm. –

-3

Như đã nêu trong các câu trả lời khác, WeakReference sẽ trả về null khi đối tượng nhọn không có tham chiếu mạnh/mềm GC đã thu hồi bộ nhớ.

Trên quy tắc chung hơn, tôi không nghĩ rằng yếu/SoftReferences là một điều tốt trong một ứng dụng. Nó làm cho mối quan tâm kết hợp của bạn:

  • ứng dụng của bạn là về logic kinh doanh
  • Các JVM và Dalvik là về quản lý bộ nhớ và tối ưu hóa mã.

Khi bạn bắt đầu sử dụng tham chiếu Yếu/Mềm, bạn giới thiệu các mối quan tâm do bộ nhớ quản lý trong ứng dụng, điều này làm cho việc phát triển/gỡ lỗi/hiểu khó hơn.

Thay vào đó, bạn có thể muốn có bộ nhớ LRU kích thước cố định (số phần tử hoặc kích thước bit).

Hy vọng điều đó sẽ hữu ích!

+2

Gabe Sechan cung cấp câu trả lời tốt nhất cho Android. Ở những nơi khác, các ứng dụng có chứa nhiều hơn logic kinh doanh, và yếu/SoftReferences có sử dụng của họ. –

+2

'Ứng dụng của bạn là về logic kinh doanh' là một chút giả định. Ứng dụng dành cho thiết bị di động không phải lúc nào cũng là trình bao bọc dịch vụ web chạy chậm và Weak References là khái niệm chính trong Bộ nhớ đệm dễ bay hơi, sử dụng nhiều ứng dụng trong các ứng dụng quan trọng về hiệu năng, cả ở phía Thiết bị di động và Máy chủ. –