2016-07-26 12 views
6

Tôi có một Fragment có một số RecyclerView.Bộ nhớ không giải phóng sau khi phân đoạn bị xóa

Trong RecyclerView này, tôi thỉnh thoảng có thể tải về và hiển thị hình ảnh (nạp với Glide vào ImageView.

Vì vậy, khi tôi mở Fragment, sử dụng bộ nhớ có thể đôi khi nhảy từ khắp nơi trên 30MB lên khoảng 100MB hoặc thậm chí nhiều hơn nữa.

Sau Activity được giữ Fragment xong, bộ nhớ không giải phóng. Nó vẫn giống như trước.

tôi đã kiểm tra Glide tài liệu hướng dẫn và rõ ràng chúng tôi không phải lo lắng về việc giải phóng Bitmaps trong RecyclerView. Đây là một vấn đề lớn, bởi vì ứng dụng thường xuyên bị treo do OOM vì điều này.

Tôi nên xử lý chính xác việc giải phóng bộ nhớ khi nào Fragment bị xóa?

Edit: quan sát khác

Một điều tôi nhận thấy là nếu tôi hoàn thành Activity và sau đó bắt đầu cùng Activity một lần nữa. Bộ nhớ sẽ nhảy xuống một lúc và sau đó sao lưu tối đa 100MB, điều này khiến tôi tin rằng bộ nhớ bị xóa trước khi khởi chạy lại Fragment.

Trả lời

4

Bộ sưu tập rác đôi khi là một vấn đề đau đớn trong Android. Hầu hết các nhà phát triển không xem xét vấn đề này và chỉ tiếp tục phát triển mà không có bất kỳ ý nghĩa nào về phân bổ nguồn lực.

Điều này tất nhiên sẽ gây ra các vấn đề về bộ nhớ như rò rỉ, OOM và ràng buộc tài nguyên không cần thiết. Hoàn toàn không có cách tự động để giải phóng bộ nhớ. Bạn có thể không, trong bất kỳ hoàn cảnh nào, chỉ dựa vào sưu tập rác

Bất cứ khi nào bạn vượt qua của của Fragment hay Hoạt động onDestroy() phương pháp, những gì bạn có thể và nên làm là xóa bất kỳ cấu trúc mà sẽ không còn được yêu cầu trong ứng dụng. Bạn có thể làm như sau:

  1. Tránh trường hợp người nghe ẩn danh. Tạo người nghe và tiêu diệt chúng khi bạn không còn cần chúng nữa.
  2. Đặt tất cả người nghe (là họ nhấp, longclick, v.v.) để trống
  3. Xóa tất cả các biến, mảng. Áp dụng các thủ tục tương tự cho tất cả các lớp và phân lớp chứa bên trong Hoạt động/Fragment
  4. Đặt biến thành vô giá trị bất cứ khi nào bạn thực hiện bất kỳ bước trước vào đó lớp nhất định (áp dụng cho tất cả các biến)

Những gì tôi đã kết thúc làm đã tạo ra một giao diện như

public interface clearMemory(){ 
    void clearMemory(); 
} 

và thực hiện nó trên mỗi lớp, có thể là hoạt động, Fragment hoặc một lớp học bình thường (bao gồm adapter, quan điểm tùy chỉnh, vv).

Sau đó tôi sẽ gọi phương thức bất cứ khi nào lớp đã bị phá hủy (vì ứng dụng đã bị phá hủy hoặc bất cứ khi nào tôi cảm thấy cần phải làm như vậy. Cẩn thận không để xử lý trong thời gian chạy bình thường)

@Override 
public void onDestroy(){ 
    clearMemory(); 
} 

public void clearMemory(){ 
    normalButtonOnClickListener = null; 
    normalButton.setOnClickListener(null); 
    normalButton = null; 
    myCustomClass.clearMemory(); // apply the interface to the class and clear it inside 
    myCustomClass = null; 
    simpleVariable = null; 
    ...   
} 

Bằng cách thực hiện điều này một cách có hệ thống, quản lý bộ nhớ ứng dụng của tôi đã trở nên dễ dàng và gọn gàng hơn. Sau đó, người ta có thể biết/kiểm soát chính xác cách thức và thời điểm bộ nhớ được xử lý.

+0

Cảm ơn, điều này chắc chắn sẽ giúp ích. Tôi sẽ cung cấp cho một thử ngày mai (mặc dù nó có thể mất một lúc trước khi tôi làm điều này trong suốt ứng dụng) và tôi sẽ cho bạn biết làm thế nào nó đi. – Guy

+0

Khi bạn nói để xóa tất cả các biến, điều đó có nghĩa là các biến mẫu, phải không? Nếu tôi tạo một biến trong phương thức onCreate, tôi có nên xóa một biến sau khi tôi ngừng sử dụng nó không? – Guy

+0

Có. Tất cả mọi thứ mà bạn phân bổ phải/nên được xử lý ngay sau khi bạn biết bạn sẽ không cần nó nữa. Như một phép ẩn dụ: 1) Bạn mua một tờ giấy dùng một lần. Bạn viết trên mảnh giấy đó một vài sự kiện về ngày của bạn 2) Bạn sẽ sử dụng mảnh giấy đó cho cả ngày nhưng bạn biết bạn sẽ không cần giấy mãi mãi 3) Đến cuối ngày, bạn nhận ra giấy bây giờ đã hoàn thành mục đích của nó. 4) Bạn loại bỏ giấy bằng cách xé nó ra và ném nó vào thùng rác. Bây giờ, hãy hiểu "mẩu giấy" như bất kỳ biến nào bạn sử dụng và "ngày" của bạn làm vòng đời hoạt động của bạn. –

1

Điều này được thêm vào câu trả lời của Ricardo.

Bạn có thể thêm đoạn mã sau để bắt đầu thu gom rác thải trong Android:
Runtime.getRuntime().gc();

Lưu ý: Gọi chức năng này sau khi bạn đã thực hiện tất cả các biến địa phương null. Việc thực thi mã này không đảm bảo rằng hệ thống sẽ thu thập rác trên ứng dụng của bạn, nó chỉ gợi ý rằng đây có thể là thời điểm tốt để thực hiện nó.
Tôi đã sử dụng điều này trong tất cả các hoạt động của mình 'onDestroy() và dường như nó hoạt động khi tôi muốn.
Hãy dùng thử, nó có thể giúp bạn.

+0

Chính xác. Một cách cơ bản có thể gọi System.gc() để "gợi ý" hệ thống, và nó cuối cùng sẽ thực hiện để thu thập tất cả các đối tượng mà không cần tham chiếu. Quản lý bộ nhớ được kiểm soát luôn là một phần thiết yếu của bất kỳ ứng dụng nào! –

Các vấn đề liên quan