2012-01-26 24 views
5

SETUP:Bộ nhớ và hoạt động :: OutOfMemory

tôi có ứng dụng này trong đó có 4 hoạt động trong một con đường tuyến tính, định vị thực sự đơn giản: A -> B -> C -> D

Tất cả các hoạt động chia sẻ cùng một hình nền và tất cả đều có một vài nút thông thường, một khung nhìn văn bản hoặc một văn bản. Tất cả đều được định nghĩa trong các tệp xml riêng biệt.

Nền là độ dốc và nặng. Khoảng 3 megs như một bitmap không nén.

Ứng dụng không làm gì được nêu ra, logic chỉ trong nó, là để bắt đầu hoạt động và đóng chúng vào nút nhấp chuột

Tôi cố gắng để sử dụng MAT để tìm một rò rỉ bộ nhớ nhưng không thể tìm thấy bất cứ điều gì. Kích thước giữ lại lớn nhất trong ứng dụng của tôi là 656 (ko?) Tổng kích thước được giữ lại cho ứng dụng là 1520 (ko?) Và tôi không thể tìm thấy bất kỳ đối tượng nào sẽ được sao chép. nào bằng cách này hoàn toàn mâu thuẫn với dumpsys trong đó cho thấy 27.300 (? Ko) phân bổ

VẤN ĐỀ:

  1. Khi tôi hướng LÊN, tôi thấy sự gia tăng của việc sử dụng bộ nhớ tương đương với kích thước nền.
  2. Khi tôi điều hướng xuống, đóng các hoạt động bằng nút quay lại hoặc lệnh kết thúc, việc sử dụng bộ nhớ của ứng dụng sẽ không giảm.
  3. Nếu tôi đi từ A đến D sau đó quay lại B và xoay màn hình, lực ứng dụng sẽ đóng với Ngoại lệ OutOfMemory.

CÂU HỎI:

Cập nhật: Tôi đoán câu hỏi thực sự là tại sao tôi có một rò rỉ bộ nhớ khổng lồ (5 megs tại một thời điểm) với kích thước ứng dụng 27megs lúc đóng băng và tôi không thể nhìn thấy nó trong MAT?

  1. Tại sao Android sẽ giải nén nhiều lần cùng một nền, một lần cho mỗi hoạt động? Có vẻ không hiệu quả.
  2. Có thể khắc phục vấn đề này bằng cách sử dụng các chủ đề hoặc tôi sẽ thấy cùng một "phân bổ 1 nền theo hoạt động" kỳ quặc?
  3. Tại sao các hoạt động không được khai hoang khi đóng cửa?
  4. Tại sao MAT và dumpsys trình bày các số khác nhau?

manh mối

Vào đúng thời tôi có: dumpsys meminfo:

Applications Memory Usage (kB): 
Uptime: 74006853 Realtime: 110962243 

** MEMINFO in pid 22683 [com.kayenko.sosadresse] ** 
        native dalvik other total 
      size: 20820  5767  N/A 26587 
     allocated: 18751  2901  N/A 21652 
      free:  312  2866  N/A  3178 
      (Pss):  1357  201 16782 18340 
    (shared dirty):  2264  1804  5456  9524 
    (priv dirty):  1280  116 16032 17428 

Objects 
      Views:  0  ViewRoots:  0 
    AppContexts:  0  Activities:  0 
      Assets:  2 AssetManagers:  2 
    Local Binders:  18 Proxy Binders:  16 
Death Recipients:  1 
OpenSSL Sockets:  0 

SQL 
       heap:  0   MEMORY_USED:  0 
PAGECACHE_OVERFLOW:  0   MALLOC_SIZE:  0 

Và cây Dominator này:

MAT Dominator tree

Thansk cho bất cứ ai với một đầu mối về những gì tôi giả sử để tìm kiếm.

Trả lời

7

Bộ nhớ là một chủ đề rất khó khăn trong Android.

Mỗi ứng dụng nhận giới hạn bộ nhớ heap tùy thuộc vào thiết bị. Bộ nhớ heap này là bộ nhớ dalvik cộng với bộ nhớ riêng, và bạn có thể xem nó như là cột tổng trong các kết quả dumpsys meminfo. Các bộ nhớ dalvik giao dịch với tất cả mọi thứ ngoại trừ với các bitmap, được phân bổ trong bộ nhớ riêng (điều này đúng cho các phiên bản Android trước khi Honeycomb).

Có nói rằng tôi chỉ có thể trả lời cho một số câu hỏi của bạn:

  1. Theo như tôi biết, Android sẽ luôn phân bổ bộ nhớ cho Bitmaps, ngay cả khi họ đều giống nhau. Vì vậy, trong trường hợp của bạn, mọi hoạt động phân bổ bộ nhớ cho nền của bạn.

  2. Tôi không biết nếu nó tốt hơn để làm việc với các chủ đề, bạn sẽ phải thử điều đó.

  3. Một mặt, các hoạt động không được khai hoang trong khi thiết bị có đủ bộ nhớ để xử lý hoạt động tiếp theo. Mỗi hoạt động được đẩy đến một đống từ nơi nó được phục hồi khi bạn nhấn nút quay lại. Trong trường hợp Android cần nhiều bộ nhớ hơn, nó loại bỏ một hoạt động từ đống deallocating bộ nhớ của nó (quay trở lại câu hỏi số một, có lẽ đây là lý do không chia sẻ bộ nhớ). Mặt khác, bạn có thể đặt hoạt động launchMode để thay đổi hành vi này (có giao diện here).

  4. Tôi nghĩ MAT không hiển thị dữ liệu bộ nhớ riêng. Sử dụng cột gốc của dumpsys meminfo để xem lượng bộ nhớ được phân bổ cho Bitmap bạn có.

Tôi đã gặp khó khăn khi tự giải quyết các vấn đề của OutOfMemory. Bây giờ tôi có một ý tưởng rõ ràng hơn nhiều hơn về cách hoạt động và tôi có thể làm việc với các tệp lớn mà không cần hết bộ nhớ. Tôi rất muốn giới thiệu hai nguồn lực này đã giúp tôi rất nhiều:

Chúc may mắn!

+0

Cảm ơn Xavi, điều này rất thông tin. Tôi đã xem các liên kết mà bạn đã cho tôi nhưng không có gì không may. Tôi không biết về launchmode và phải thừa nhận tôi không hiểu gì về những gì nó phải làm. Tôi đoán tôi sẽ phải kiểm tra nó bởi vì các tài liệu cũng như bình thường 'thiếu' :) – Yahel

+1

Tôi sẽ đánh dấu câu trả lời của bạn là câu trả lời mặc dù bởi vì bạn thực sự đã cho tôi 3 câu trả lời trong 4: D – Yahel

0

Bạn cần phải tái chế một cách rõ ràng Bitmap được sử dụng làm nền khi bạn hủy hoạt động của mình. Mã sẽ giống như sau:

@Override 
protected void onDestroy() { 
    Drawable drawable = getView().getBackground(); 
    if (drawable instanceof BitmapDrawable) { 
     ((BitmapDrawable)drawable).getBitmap().recycle(); 
    } 
    drawable.setCallback(null); 
    getView().setBackgroundDrawable(null); 
    super.onDestroy(); 
} 

Có thể bạn cần phải giải phóng tài nguyên một cách đệ quy cho các chế độ xem lồng nhau, nhưng tùy thuộc vào cấu trúc bố cục của bạn. Đây là trường hợp chung

+0

Cảm ơn các đầu vào, tiếc là nó đã không giúp gì cả. Không có tiện ích nào của tôi có bitmapdrawables theo mã của bạn và tôi cũng đã thử mã từ trang này: http://www.alonsoruibal.com/bitmap-size-exceeds-vm-budget/ và sau đó kết hợp cả hai là kích thích càng tốt nhưng không có kết quả. – Yahel

+0

Tôi không đồng ý. Dalvik sẽ tự động tái chế các ảnh bitmap khi không có thêm tham chiếu đến nó. Nó không phải là cần thiết để làm điều này bằng tay, phương thức recycle() tồn tại để bạn có thể vội vàng quá trình này và đòi lại bộ nhớ trước. –

4

Vì vậy, sau giờ làm điều tra và sự giúp đỡ của Xavi ở đây là kết quả:

Q. Tại sao Android giải nén nhiều lần cùng một nền, một lần mỗi hoạt động? Có vẻ không hiệu quả.

A. Mặc dù có vẻ logic để có một số cách để yêu cầu bitmap được chia sẻ trên các hoạt động vì chúng tôi đang sử dụng thiết bị di động với ít bộ nhớ, điều này dường như không tồn tại trong Android. Mỗi lần một bitmap được sử dụng trong các hoạt động khác nhau, nó không nén vào bộ nhớ riêng.

Q. Có thể khắc phục vấn đề này bằng cách sử dụng chủ đề hoặc tôi sẽ thấy cùng "phân bổ một bitmap theo hoạt động" kỳ quặc?

Sau khi thử nghiệm, bộ nhớ được tiêu thụ bằng cách sử dụng các chủ đề không khác chút nào so với lượng bộ nhớ được sử dụng bằng cách đặt rõ ràng bitmap trong xml của bố cục. Điều này là lạ đối với tôi kể từ khi tạo kiểu là về việc nhóm các thuộc tính cho cùng một vị trí.

Q. Tại sao các hoạt động không được khai hoang khi đóng?

A. Tôi không chắc nhưng những gì tôi thấy là điều này đã cho tôi lỗi OOM gần như chỉ khi gỡ lỗi. Khi khởi chạy ứng dụng từ thiết bị, hầu như không bao giờ xảy ra. Một trục trặc trong quá trình gỡ lỗi? Hãy thử nó trước khi bạn mất 5 giờ thử nghiệm một điều zillion.

Q. Tại sao MAT và dumpsys trình bày các số khác nhau?

A. Câu trả lời của Xavi là chính xác, dumpsys meminfo hiển thị tất cả bộ nhớ được phân bổ (native + dalvik) trong khi MAT chỉ hiển thị một Dalvik. Vì các pixel bitmap được cấp phát trong bộ nhớ riêng, MAT sẽ không nhìn thấy nó. Điều này chỉ đúng trước Android 3.0, nơi họ thay đổi lược đồ phân bổ và làm cho dữ liệu pixel của bitmap phù hợp với Dalvik.

Q. Làm sao tôi giải quyết vấn đề của tôi

A. Đầu tiên điều này có thể không phải là một vấn đề khi không gỡ lỗi. Thứ hai, để được ở bên an toàn tôi đã thay thế gradient png với một hình dạng với một gradient xuyên tâm và sử dụng các

getWindow().setFormat(PixelFormat.RGBA_8888); 
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DITHER); 

trong onCreate các hoạt động của tôi để cố gắng tránh dải. Tôi vẫn sẽ có dải trên một số thiết bị nhưng tôi muốn có dải hơn FCs

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