Android之读取大图片内存溢出
2015-08-14 11:43
405 查看
在工作的过程中,相信很多朋友会遇到读取本地图片,由于图片过大,报出outOfMemory的错误,导致crash。
那是因为大部分朋友都是通过setImageBitmap或setImageResource或BitmapFactory.decodeResource或BitmapFactory.decodeFile来设置图片,
这些函数在完成decode后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存。
因此,改用先通过BitmapFactory.decodeStream方法,创建出一个bitmap,再将其设为ImageView的
source,
decodeStream最大的秘密在于其直接调用JNI>>nativeDecodeAsset()来完成decode,
无需再使用java层的createBitmap,从而节省了java层的空间。
如果在读取时加上图片的Config参数,可以跟有效减少加载的内存,从而跟有效阻止抛out of Memory异常
另外,decodeStream直接拿的图片来读取字节码了, 不会根据机器的各种分辨率来自动适应,
使用了decodeStream之后,需要在hdpi和mdpi,ldpi中配置相应的图片资源,
否则在不同分辨率机器上都是同样大小(像素点数量),显示出来的大小就不对了。
下面看代码
那是因为大部分朋友都是通过setImageBitmap或setImageResource或BitmapFactory.decodeResource或BitmapFactory.decodeFile来设置图片,
这些函数在完成decode后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存。
因此,改用先通过BitmapFactory.decodeStream方法,创建出一个bitmap,再将其设为ImageView的
source,
decodeStream最大的秘密在于其直接调用JNI>>nativeDecodeAsset()来完成decode,
无需再使用java层的createBitmap,从而节省了java层的空间。
如果在读取时加上图片的Config参数,可以跟有效减少加载的内存,从而跟有效阻止抛out of Memory异常
另外,decodeStream直接拿的图片来读取字节码了, 不会根据机器的各种分辨率来自动适应,
使用了decodeStream之后,需要在hdpi和mdpi,ldpi中配置相应的图片资源,
否则在不同分辨率机器上都是同样大小(像素点数量),显示出来的大小就不对了。
下面看代码
private void getBitmap1() { // 1.会导致内存溢出 Bitmap bitmap = null; bitmap = BitmapFactory.decodeFile(path); imageView.setImageBitmap(bitmap); bitmap.recycle(); } private void getBitmap2() { // 2.会导致内存溢出 imageView .setImageDrawable(getResources().getDrawable(R.drawable.world)); } private void getBitmap3() { // 3.不会导致内存溢出 InputStream is = getResources().openRawResource(R.drawable.world); BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = false; options.inSampleSize = 10; // width,hight设为原来的十分一 Bitmap btp = BitmapFactory.decodeStream(is, null, options); imageView.setImageBitmap(btp); btp.recycle(); } private void getBitmap4() { new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub // 4.不会导致内存溢出 Bitmap bitmap = null; File file = new File(path); InputStream is = null; try { is = new FileInputStream(file); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } // bitmap = BitmapFactory.decodeStream(is); BitmapFactory.Options opt = new BitmapFactory.Options(); opt.inPreferredConfig = Bitmap.Config.RGB_565; opt.inPurgeable = true; opt.inInputShareable = true; opt.inSampleSize = 10; bitmap = BitmapFactory.decodeStream(is, null, opt); Message msg = new Message(); msg.obj = bitmap; handler.sendMessage(msg); // imageView.setImageBitmap(bitmap); // bitmap.recycle(); } }) { }.start(); } private Handler handler = new Handler() { public void handleMessage(android.os.Message msg) { imageView.setImageBitmap((Bitmap) msg.obj); }; };
相关文章推荐
- Android文件存储
- android中listview分页加载数据
- Android客户端和服务端如何使用Token和Session
- android抽屉实现
- Android中SMS的接收处理
- android 安装目录介绍
- php、java、android、ios通用的3des加密方法
- Android Studio导入JAR包(以ButterKnife为例)
- Android fragment 只让一个fragment支持横屏
- ubuntu 14.04 编译android4.0 出现gcc-version.sh: line 11: cc: command not found错误解决方法
- Android 学习之逐帧动画(Frame)
- Android 导入v7包常见错误,以及项目引用v7包错误解决,
- 史上最简单的android图片自动轮播
- Android签名打包后应用HOME键重启
- 实现android基于百度的定位
- android中实现带图片和checkbox的listview
- android使用socket实现实时视频
- android:inputType参数类型说明
- [转]Android Studio 1.3.1环境搭建
- Android应用:Service开发实例(二)之Service的两种创建方法和其生命周期