有效解决Android加载大图片内存溢出的问题
解决Android加载大图片内存溢出的问题
非著名程序员
今天在交流群里,有人问我他经常遇到加载图片时内存溢出的问题,遇到的情况还是在自己的测试机或者手机里没有问题,做好了, 到了客户手机里就内存溢出了。其实有时候不同的手机和不同的系统对内存的要求不一样,尤其是图片,所以可能会遇到这样的问题。那我们怎么样有效解决Android加载大图片时内存溢出的问题? 那么接下来,我们就来说说这个问题: 首先,我们要知道尽量的不要使用setImageResource或setImageBitmap或BitmapFactory.decodeResource来设置一张大图,因为这些函数在完成decode后,最终都是要通过java层的createBitmap来完成的,需要消耗很多的内存。所以,我们应该先通过BitmapFactory.decodeStream方法,创建出一个bitmap,再将其设为ImageView的 source,decodeStream最大的好处和秘密在于其直接调用JNI>>nativeDecodeAsset()来完成decode,无需再使用java层的createBitmap,从而节省了java层的内存空间。 其实,如果在读取时加上图片的Config参数,可以很有效的减少加载的内存,从而能很有效的阻止抛out of Memory异常。 另外,decodeStream直接拿的图片来读取字节码了,不会根据机器的各种分辨率来自动适应屏幕, 使用了decodeStream之后,需要在hdpi和mdpi,ldpi中配置相应的图片资源, 否则在不同分辨率机器上都是同样大小,显示出来的大小就不对了,不适配。 现在给大家比较好用的方法,如下:
/**
* 以最省内存的方式读取本地资源的图片
*
* @param context
* @param resId
* @return
*/
public static Bitmap readBitMap(Context context, int resId) {
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inPreferredConfig = Bitmap.Config.RGB_565;
opt.inPurgeable = true;
opt.inInputShareable = true;
// 获取资源图片
InputStream is = context.getResources().openRawResource(resId);
return BitmapFactory.decodeStream(is, null, opt);
}
其实通过下面的两种方式也可以:
1. InputStream is = this.getResources().openRawResource(R.drawable.pic1);
BitmapFactory.Options options=new BitmapFactory.Options();
options.inJustDecodeBounds = false;
options.inSampleSize = 5; //width,hight设为原来的五分之一
Bitmap btp =BitmapFactory.decodeStream(is,null,options);
2. if(!bmp.isRecycle() ){
bmp.recycle() //回收图片所占的内存
system.gc() //提醒系统及时回收
}
我也稍微再说一下图片占用进程的内存算法吧: android中处理图片的基础类是Bitmap,顾名思义,就是位图。占用内存的算法如下:图片的width*height*Config。如果Config设置为ARGB_8888,那么上面的Config就是4。一张480*320的图片占用的内存就是480*320*4 byte。其实是在默认情况下android进程的内存占用量为16M,因为Bitmap他除了java中持有数据外,底层C++的skia图形库还会持有一个SKBitmap对象,因此一般图片占用内存推荐大小应该不超过8M。这个大小是可以调整,但是只有在编译源代码时可以设置这个大小的参数。
- hadoop源码解析2 - conf包中Configuration.java解析
- junit入门实例
- cordova插件- Network Information
- SpringCloud配置中心客户端读取配置
- cordova插件- Inappbrowser
- SpringCloud配置中心高可用搭建
- hadoop压缩与解压
- cordova插件- Media
- JDK8之新特性扩展篇
- Java管理Cookie增删改查操作。
- Intellij Idea乱码解决方案都在这里了
- 神奇,教你用随机数打印hello world
- Mapreduce任务实现邮件监控
- Eclipse中Maven打包程序并在Linux中运行
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- Qt 第二步 槽与信号(一) 实现点击按钮并弹窗
- python3 爬虫第一步 简单获取网页基本信息
- python3 爬虫第二步Selenium 使用简单的方式抓取复杂的页面信息
- Qt 第二步 熟悉文件结构组成(二)
- php基础教程 第一步 环境配置及helloworld
- 推荐两个Docker配置检查与启动异常修复方法脚本
- 持续集成gitlab-ci.yml配置文档基础
- php基础教程 第二步 通俗易懂的学习变量、常量与数据类型
- git | Windows下如何利用Linux的命令
- python3 爬虫第三步 本文包你学会正则 不会就来锤我
- php基础教程 第三步 学习字符串及相关函数
- php基础教程 第四步 学习运算符
- php基础教程 第五步 逻辑控制
- php基础教程 第六步 学习数组以及条件判断switch补充
- php基础教程 第七步数组补充及循环基础