2012-05-20 44 views
28

Tôi khá mới phát triển Android và dường như tôi không thể hiểu ngoại lệ Java Out of Memory. Tôi biết điều đó có nghĩa là ứng dụng của tôi đã vượt qua ngân sách VM nhưng sau khi Googling điều này nhiều lần tôi vẫn không có vẻ nắm bắt khái niệm này. Tôi e rằng ứng dụng của tôi sử dụng quá nhiều bộ nhớ vì tôi có sáu bộ chọn nút trên mỗi màn hình với hai bitmap cho mỗi bộ chọn khoảng 20 kb mỗi bộ theo tab thuộc tính. Trên G2x gốc của tôi, tôi đã đặt ngân sách VM thành 12mb, khởi động lại điện thoại và chạy ứng dụng của mình mà không gặp bất kỳ vấn đề gì. Tôi unbinding drawables trên mỗi onDestroy() và gợi ý tại GC để chạy ở đây cũng có. Sau khi sử dụng ứng dụng một thời gian trong trình mô phỏng, tôi nhấp vào "Nguyên nhân GC" trên màn hình DDMS của tôi và kết quả là ID = 1, Kích thước Heap 6,33 MB, Phân bổ 2,895 MB, Miễn phí 3,28 MB,% Được sử dụng 47,20, # Đối tượng 52,623.Android Hiểu kích thước Heap

Đây là nơi tôi không hiểu điều gì đang xảy ra, trình giả lập của tôi được đặt thành 24MB VM. Số đó ở đâu? Vấn đề thực tế tôi gặp phải là nếu tôi thiết lập giả lập 16MB VM, ứng dụng của tôi gặp sự cố thứ hai với ngoại lệ Out of Memory. Làm thế nào đến nó không sụp đổ trên điện thoại của tôi với VM thiết lập đến 12 MB hoặc trên điện thoại HTC Magic cũ của tôi với 12 MB cổ phiếu VM? Các bạn có nghĩ ứng dụng của tôi đang chiếm quá nhiều bộ nhớ không? Tôi không biết liệu những số DDMS đó có tốt hay không. Cảm ơn vì đã dành thời gian cho tôi.

Đối với mã của tôi, tôi có mọi hình ảnh được chỉ định trong bố cục XML Tôi không thực hiện bất kỳ điều gì theo lập trình với chúng ngoại trừ việc thêm người nghe vào chúng. Tôi tìm thấy mã này ở đây và tôi đã thêm nó vào mọi hoạt động mà tôi có ...

@Override 
protected void onDestroy() { 
    super.onDestroy(); 

    unbindDrawables(findViewById(R.id.myRootLayout)); 
    System.gc(); 
} 

private void unbindDrawables(View view) { 
    if (view.getBackground() != null) { 
     view.getBackground().setCallback(null); 
    } 
    if (view instanceof ViewGroup && !(view instanceof AdapterView)) { 
     for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) { 
      unbindDrawables(((ViewGroup) view).getChildAt(i)); 
     } 
     ((ViewGroup) view).removeAllViews(); 
    } 
} 

Nếu không, tất cả những gì tôi làm là thêm onClickListeners vào các nút có hình nền PNG. Tôi muốn tìm hiểu làm thế nào để chỉ định nền nút lập trình nhưng tôi cần phải có các chức năng chọn như trên tập trung, trên báo chí, không tập trung nhưng ép vv để làm cho nền nút thay đổi theo tương tác người dùng. Tôi đã xem xét các tài liệu về điều này nhưng nó có vẻ áp đảo, đó là lý do tại sao tôi figured tôi bắt đầu ở đây với những điều cơ bản của quản lý Heaps và làm việc theo cách của tôi lên để xác định selectors trong mã. Điều này có thể không có ý nghĩa nhưng có một số lượng "khỏe mạnh" phân bổ bộ nhớ mà một ứng dụng có thể phân bổ mà không nhận được gần với Out of Memory ngoại lệ? Ví dụ nếu một ứng dụng được phân bổ 6MB, nó sẽ ổn nhưng 8MB sẽ đẩy nó, có giới hạn như thế trong phân bổ bộ nhớ không? Cảm ơn Alex Lockwood lần nữa vì câu trả lời của bạn Tôi sẽ đọc và đọc lại nó cho đến khi công cụ này có ý nghĩa với tôi

Trả lời

50

Khi bạn đặt ngân sách VM trên trình mô phỏng/thiết bị của mình, những gì bạn đang làm kích thước tối đa được phép. Khi chạy, vùng heap phát triển theo kích thước động khi máy ảo Dalvik yêu cầu bộ nhớ hệ thống từ hệ điều hành. Máy ảo Dalvik thường bắt đầu bằng cách phân bổ một đống tương đối nhỏ. Sau đó, sau mỗi lần chạy GC nó kiểm tra để xem có bao nhiêu bộ nhớ heap miễn phí. Nếu tỷ lệ heap tự do cho tổng số heap quá nhỏ, máy ảo Dalvik sau đó sẽ thêm nhiều bộ nhớ hơn vào heap (tối đa kích thước heap được cấu hình tối đa).

Điều đó đang được nói, lý do tại sao bạn không nhìn thấy "24 mb" trên màn hình DDMS của bạn là do đống chưa phát triển đến kích thước tối đa của nó. Điều này cho phép Android tận dụng tốt dung lượng bộ nhớ đã có sẵn trên thiết bị cầm tay.

Đối với lý do tại sao ứng dụng của bạn gặp sự cố trên trình mô phỏng và không phải là điện thoại của bạn, điều đó có vẻ lạ (bạn có chắc là các số này chính xác không?). Tuy nhiên, bạn nên nhớ rằng bộ nhớ đó được quản lý động và tổng dung lượng bộ nhớ được xác định dựa trên một số yếu tố bên ngoài (tốc độ/tần suất mà bộ sưu tập rác được thực hiện, v.v.).

Cuối cùng, vì những lý do tôi đã đề cập ở trên, rất khó để nói chắc chắn ứng dụng của bạn quản lý bộ nhớ dựa trên một dòng thông tin bạn đã cung cấp ở trên. Chúng tôi thực sự cần xem một số mã của bạn.Tuy nhiên, OutOfMemoryError s chắc chắn đáng đáng lo ngại, vì vậy tôi chắc chắn sẽ xem xét việc sử dụng bộ nhớ của ứng dụng của bạn. Một điều bạn có thể xem xét là lấy mẫu hình ảnh bitmap của bạn trong thời gian chạy với các cuộc gọi đến inSampleSize bằng cách sử dụng lớp BitmapFactory. Điều này có thể giúp giảm lượng bộ nhớ cần thiết để tải bitmap có thể vẽ của bạn. Hoặc là hoặc bạn có thể giảm độ phân giải của drawables của bạn (mặc dù 20 kb mỗi âm thanh tốt với tôi).

+3

+1, câu trả lời rất có nhiều thông tin! –

+0

Cảm ơn bạn rất nhiều! Tôi đã học được rất nhiều từ đó. Tôi đang thêm một số thông tin vào cuối câu hỏi –

+0

Nhận xét về độ phân giải lại "20 kb mỗi âm thanh đều ổn" - AFAIK, không quan trọng kích thước tệp * là gì (sẽ nhỏ hơn đối với hình ảnh nén tốt hơn), điều quan trọng là * DIMENSIONS * là gì; trong bộ nhớ, với màu sắc đầy đủ, sẽ lấy 4B mỗi pixel, phải không? Do đó, điều quan trọng là phải thay đổi kích thước hình ảnh khi bạn tải nó [android docs - Tải một phiên bản thu nhỏ xuống bộ nhớ], dựa trên kích thước thực tế cần thiết, cho thiết bị hiện tại. – ToolmakerSteve

16

Ngay cả khi ứng dụng của bạn không đạt đến giới hạn heap "24mb" (thay đổi bên trong thiết bị), bạn vẫn có thể gặp sự cố vì Android mất một khoảng thời gian để tăng dung lượng cho ứng dụng của bạn.

Trong trường hợp của tôi, tôi đã tạo và đổ một vài hình ảnh trong một khoảng thời gian ngắn.

Khá thường xuyên, tôi đã nhận được OutOfMemoryError.

Có vẻ như Android không đủ nhanh để phát triển không gian heap cho ứng dụng của tôi.

Tôi tin rằng tôi đã giải quyết vấn đề này bằng cách sử dụng cài đặt largeHeap trong tệp kê khai. Với cài đặt đó trên, Android để lại nhiều bộ nhớ miễn phí hơn mỗi khi nó phát triển vùng heap, giảm thiểu tối đa khả năng đạt đến giới hạn hiện tại.

Tôi không sử dụng giới hạn 24mb nhưng điều này largeHeap conf khá tiện dụng.

Bạn chỉ cần thiết lập largeHeap="true" trên thẻ ứng dụng của bạn AndroidManifest.xml

<application 
    android:icon="@drawable/ic_launcher" 
    android:label="@string/app_name" 
    android:largeHeap="true" 
    android:theme="@style/AppTheme" > 

Tuy nhiên, chắc chắn rằng bạn đang cẩn thận khi giao dịch với những hình ảnh, giống như @ Alex Lockwood khuyên.

+16

Sử dụng bigHeap = "true" với dịch vụ chăm sóc tối đa. Bởi vì việc sử dụng điều này có thể ảnh hưởng xấu đến hiệu ứng ứng dụng của bạn.Bởi vì bạn đang yêu cầu hệ thống tăng giới hạn heap tối đa. Khi điều này xảy ra, sẽ tốn nhiều thời gian hơn cho việc thu gom rác thải. Nếu bạn kiểm tra nhật ký, bạn có thể thấy thời gian GC Tạm dừng sẽ lớn hơn. Lý tưởng nhất nó nên được giữa 2-5ms.Trong trường hợp này nó có thể thay đổi thậm chí tối đa 30-45ms. Vì vậy, không thiết lập tài sản heap lớn để đúng chỉ vì bạn đang nhận ra bộ nhớ. Sử dụng nó như là bước cuối cùng. Nếu không, nó sẽ là một hit hoàn hảo. –

+0

Thật vậy. Trong trường hợp của tôi, tôi đang xử lý rất nhiều hình ảnh chất lượng cao và trước khi sử dụng tùy chọn bigHeap, tôi đã triển khai mã: - tải hình ảnh được lấy mẫu - đổi kích thước hình ảnh thành phù hợp hoàn hảo - xoá hình ảnh không sử dụng khỏi bộ nhớ - lưu hình ảnh trong "đĩa" Tôi vẫn gặp sự cố được giải quyết chỉ với tùy chọn bigHeap. Tuy nhiên, chỉ sử dụng nó sau khi thử mọi thứ khác, như @SanalVarghese khuyên. – tbraun

+0

Chỉ cần thêm vào điều này, tôi đã có vô số vấn đề với bộ nhớ của ứng dụng của nó kích thước của nó tăng lên rất nhiều. Nó có thể không được thiết lập với nhau một cách hiệu quả vào thời điểm này nhưng nó nên đã có thể không exeed giới hạn heep. Tuy nhiên nó sẽ không bao giờ phát hành nhiều tài nguyên. Vì một số lý do, nó thực hiện rất tốt sau khi áp dụng tùy chọn bigHeap. Cảm ơn nhiều. –

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