如何使用 BitmapFactory.decodebyteArray() 提高内存使用率?
在一个线程中,我(从套接字)获取 jpg 图像并将其放入字节数组 datas[]
中。 然后我制作一个位图并将其发送到我的用户界面以在图像视图中显示它:
线程端:
bundle.putParcelable("image", BitmapFactory.decodeByteArray(this.datas, 0, jpgSize,this.bitmapOption));
message.what = ThreadMessages.MSG_IMAGE_AVAILABLE;
message.setData(bundle);
this.uiHandler.sendMessage(message);
位图选项定义如下:
this.bitmapOption = new BitmapFactory.Options();
this.bitmapOption.inPurgeable = true;
ui 端:
cameraView.setImageBitmap((Bitmap) bundle.getParcelable("image"));
据我所知它在 Android 2.x 和 4.0.x 的手机上运行良好。但我用 GalaxyTab 8.9 (android 3.1) 做了一些测试,由于内存使用率很高,我的 Activitie 被系统杀死了:
01-30 14:12:02.311: I/ActivityManager(72): Process my.package (pid 1175) has died.
01-30 14:12:02.321: I/WindowManager(72): WIN DEATH: Window{41140848 my.package/my.package.DisplayOneCam paused=false}
01-30 14:12:02.331: I/WindowManager(72): WIN DEATH: Window{410f5020 my.package/my.package.main paused=false}
01-30 14:12:02.331: I/WindowManager(72): WIN DEATH: Window{41033308 my.package/my.package.DisplayCameras paused=false}
01-30 14:12:02.371: I/ActivityManager(72): Start proc my.package for activity my.package/.DisplayCameras: pid=1209 uid=10036 gids={3003, 1015}
01-30 14:12:02.371: I/ActivityManager(72): Low Memory: No more background processes.
01-30 14:12:02.391: I/WindowManager(72): WINDOW DIED Window{410f5020 my.package/my.package.main paused=false}
获取的位图不是非常高分辨率的图片(最大 800*600),但它显示在至少 10 fps(如果可能的话更高)。 使用 inPurgeable 选项可以让我避免 OOM 崩溃(我在使用 inPurgeable 之前就遇到过),但这似乎还不够。 使用 inSampleSize (如奇怪的内存不足问题中所述)似乎并不成为一个解决方案,因为它调整图像的大小,并且我需要一个占据图像视图的整个空间的图像。
知道我正在字节数组中接收 jpg 并且需要在图像视图中显示它,如何提高内存使用率?
注意:我不需要/想要调整位图大小,收到的 jpg 大小已经很好。
注2:在每次decodeByteArray之后触发system.gc()似乎可以解决问题,但它很难看并且性能急剧下降
In a thread i'm fetching a jpg image (from a socket) and putting it in a byte array datas[]
.
Then i make a bitmap and send it to my ui to display it in an imageview :
Thread side :
bundle.putParcelable("image", BitmapFactory.decodeByteArray(this.datas, 0, jpgSize,this.bitmapOption));
message.what = ThreadMessages.MSG_IMAGE_AVAILABLE;
message.setData(bundle);
this.uiHandler.sendMessage(message);
The bitmap option is defined as following :
this.bitmapOption = new BitmapFactory.Options();
this.bitmapOption.inPurgeable = true;
ui side :
cameraView.setImageBitmap((Bitmap) bundle.getParcelable("image"));
As far i know it's works fine on phone with android 2.x and 4.0.x. But i have made some test with a galaxyTab 8.9 (android 3.1) and my activitie is killed by the system due to a high memory usage :
01-30 14:12:02.311: I/ActivityManager(72): Process my.package (pid 1175) has died.
01-30 14:12:02.321: I/WindowManager(72): WIN DEATH: Window{41140848 my.package/my.package.DisplayOneCam paused=false}
01-30 14:12:02.331: I/WindowManager(72): WIN DEATH: Window{410f5020 my.package/my.package.main paused=false}
01-30 14:12:02.331: I/WindowManager(72): WIN DEATH: Window{41033308 my.package/my.package.DisplayCameras paused=false}
01-30 14:12:02.371: I/ActivityManager(72): Start proc my.package for activity my.package/.DisplayCameras: pid=1209 uid=10036 gids={3003, 1015}
01-30 14:12:02.371: I/ActivityManager(72): Low Memory: No more background processes.
01-30 14:12:02.391: I/WindowManager(72): WINDOW DIED Window{410f5020 my.package/my.package.main paused=false}
The fetched bitmap is not a very high res pictures (800*600 max) but it is displayed at least at 10 fps (more if it's possible).
Using the inPurgeable option lets me avoid the OOM crash (i had it before using inPurgeable) but it not seem to be enough .
Using inSampleSize (like explained in Strange out of memory issues) don't seems to be a solution because it resize the image, and i need a image which take the entire space of the imageview.
How can i improve my memory usage knowing that i'm receiving a jpg in a byte array and i need to display it in a imageview ?
Note : i don't need/want to resize the bitmap, the received jpg is already well sized.
Note 2 : Triggering system.gc() after each decodeByteArray seems to solve th eproblem, but it's ugly and performance are slowing down drasticly
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
使用 Parcelable 在 Intents 中发送大量数据是一个坏主意,并且可能会导致性能不佳。您最好将图像存储到持久存储中,并将 URI 传递给存储的图像而不是图像数据本身。
如何做你使用bundle在android Activity之间传递图像(位图)吗?
Using Parcelable to send large amounts of data in Intents is a bad idea and is likely to result in poor performance. You would be better to store the image to persistent storage, and pass a URI to the stored image instead of the image data itself.
There is some more info on this in how do you pass images (bitmaps) between android activities using bundles?
如果您仅在应用程序进程中传递消息,则无需使用 Bundle。只需在 Message.obj 中传递位图即可。
There is no need to use a Bundle if you're only passing the Message within your application process. Simply pass your Bitmap in Message.obj.