Tôi sẽ rất biết ơn nếu ai đó có thể xác nhận rằng tôi đã giải quyết vấn đề dưới đây một cách chính xác hoặc nếu có giải pháp thay thế?Android Bitmap tải hết lỗi bộ nhớ Galaxy S3 WXGA
Tôi có một ứng dụng tải hình ảnh lớn (ví dụ: 800 * 1720 pixel) vào bộ nhớ và hiển thị hình ảnh đó trong chế độ xem cuộn. Hình ảnh là một kế hoạch sàn cho một bảo tàng và tôi muốn có một bản đồ đơn giản như trải nghiệm di chuyển và phóng to. Các hình ảnh được tải tốt trên các thiết bị cũ, nhưng gây ra một lỗi bộ nhớ trên Samsung Galaxy S3.
Nhìn vào các thông điệp LogCat nó bật ra rằng trong creaing bitmap 22MB đã được cấp phát cho bitmap thay vì 800 * 1720 * 4 = 5,5MB. Về cơ bản 4x bộ nhớ được phân bổ theo yêu cầu của các thiết bị khác và đẩy mức sử dụng bộ nhớ lên trên kích thước heap 50MB.
Giải pháp được đề xuất cho vấn đề này là sử dụng tùy chọn BitmapFactory.Options.inSampleSize
để giảm độ phân giải của hình ảnh được tải và yêu cầu ít bộ nhớ hơn. Tuy nhiên, điều này làm giảm chất lượng của hình ảnh, và tôi thực sự muốn hiển thị nó ở kích thước đầy đủ ở chất lượng gốc khi hoạt động tốt trên các thiết bị cũ hơn.
Sau nhiều lần cào xước, tôi kết luận rằng vấn đề là mật độ pixel trên màn hình WXGA của S3 là 2.0 và do đó đối với mỗi pixel trong ảnh, bitmap thực sự phân bổ 4 pixel. Với một chút thử và sai tôi phát hiện ra tôi có thể ngăn chặn điều này xảy ra bằng cách thiết lập options.inScaled = false;
http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html#inScaled
Trên đường đi, tôi cũng nhận ra rằng tôi có thể cắt giảm sử dụng bộ nhớ của tôi trong nửa để 2.7MB bằng cách sử dụng một độ chính xác thấp độ sâu màu của 2 pixel thay vì 4 pixel bằng cách đặt options.inPreferredConfig = Bitmap.Config.RGB_565;
. Đối với floorpans của tôi điều này đã không ảnh hưởng đến chất lượng hình ảnh có thể nhìn thấy.
Mã cuối cùng là như sau:
String uri = "drawable/floorplan";
int imageResource = getResources().getIdentifier(uri, null, getPackageName());
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
options.inScaled = false;
Bitmap bm = BitmapFactory.decodeResource(getResources(), imageResource, options);
IVfloorplan.setImageBitmap(bm);
Khi hiển thị bitmap này bạn cần phải mở rộng nó lại lên. Để làm việc ra các tỉ lệ bạn có thể có được mật độ điểm ảnh từ:
float density = getResources().getDisplayMetrics().density;
tôi giảm sử dụng bộ nhớ cho bitmap từ 22MB đến 2.7MB, mà trong một đống 50MB rất có ý nghĩa.
Phân tích tốt và cảm ơn bạn đã giải pháp. – Simon
Tôi nghĩ, có thể là tốt để cung cấp liên kết tài liệu ở đây mô tả một phần giống như vậy liên quan đến inSampleSize: http://developer.android.com/training/displaying-bitmaps/load-bitmap.html. Và http://www.curious-creature.org/2010/12/08/bitmap-quality-banding-and-dithering/ về chơi với định dạng màu bitmap và đạo cụ/khuyết điểm của nó. – sandrstar
tuyệt vời. Tôi nghĩ rằng điều này sẽ giúp ngay cả đối với các thiết bị khác có kích thước heap thấp hơn. Nhưng bạn nên thêm câu trả lời thay vì trả lời câu hỏi của bạn, vì nó vi phạm các quy tắc SO và làm cho câu hỏi an toàn khỏi bị xóa. –