Android 中对于图片的内存优化方法

   2015-08-27 0
核心提示:Android 中对于图片的内存优化方法,需要的朋友可以参考一下

1. 对图片本身进行操作

尽量不要使用 setImageBitmap、setImageResource、 BitmapFactory.decodeResource 来设置一张大图,因为这些方法在完成 decode 后,最终都是通过 Java 层的 createBitmap 来完成的,需要消耗更多内存。因此,改用先通过 BitmapFactory.decodeStream 方法,创建出一个 bitmap,再将其设为 ImageView 的 source,decodeStream 最大的秘密在于其直接调用 JNI>>nativeDecodeAsset() 来完成 decode,无需再使用 Java 层的 createBitmap,从而节省了 Java 层的空间。如果在读取时加上图片的 Config 参数,可以更有效的减少加载的内存,从而更有效阻止抛出内存异常。另外,decodeStream 直接拿图片来读取字节码了,不会根据机器的各种分辨率来自动适应,使用了 decodeStream 之后,需要在 hdpi 和 mdpi,ldpi 中配置相应的图片资源, 否则在不同分辨率机器上都是同样大小(像素点数量),显示出来的大小就不对了。

复制代码 代码如下:

InputStream is = this.getResources().openRawResource(R.drawable.pic);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = false;
options.inSampleSize = 2;
Bitmap btp =BitmapFactory.decodeStream(is,null,options);

以上代码即是读取 drawable 下名为 pic 图片的缩略图,长度、宽度都只有原图片的 1/2。图片大小减少,占用的内存自然也变小了。这么做的弊端是图片质量变差,inSampleSize 的值越大,图片的质量就越差。由于各手机厂商缩放图片的算法不同,在不同手机上的缩放图片质量可能会不同。

2. 调用图片的 recycle() 方法

复制代码 代码如下:

if(!bmp.isRecycle() ){
   bmp.recycle()    //回收图片所占的内存
   system.gc()      //提醒系统及时回收
}

这种方法其实不是真正降低图片内存的方法。主要目的是标记图片对象,方便回收图片对象的本地数据。图片对象的本地数据占用的内存最大,而且与程序 Java 部分的内存是分开计算的。所以经常出现 Java heap 足够使用,而图片发生 OutOfMemoryError 的情况。在图片不使用时调用该方法,可以有效降低图片本地数据的峰值,从而减少 OutOfMemoryError 的概率。不过调用了 recycle() 的图片对象处于“废弃”状态,调用时会造成程序错误。所以在无法保证该图片对象绝对不会被再次调用的情况下,不建议使用该方法。特别要注意已经用 setImageBitmap(Bitmap
img) 方法分配给控件的图片对象,可能会被系统类库调用,造成程序错误。

 

3. 以最省内存的方式读取本地资源的图片

复制代码 代码如下:

/**
 * 以最省内存的方式读取本地资源的图片
 */
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); 
}

Android 中加载图片的颜色模式有四种,分别是:ALPHA_8:每个像素占用 1byte 内存、ARGB_4444:每个像素占用 2byte 内存、ARGB_8888:每个像素占用 4byte 内存、RGB_565:每个像素占用 2byte 内存。Android默认的颜色模式为ARGB_8888,这个颜色模式色彩最细腻,显示质量最高。但同样的,占用的内存也最大。以上代码即是将图片资源以 RGB_565 (或以 ARGB_4444)模式读出。内存减少虽然不如第一种方法明显,但是对于大多数图片,看不出与 ARGB_8888 模式有什么差别。不过在读取有渐变效果的图片时,可能有颜色条出现。另外,会影响图片的特效处理。

 

4. 使用 Matrix 对象放大的图片如何更改颜色模式:

虽然使用 Matrix 对象放大图片,必定会耗费更多的内存,但有时候也不得不这样做。放大后的图片使用的 ARGB_8888 颜色模式,就算原图片是ARGB_4444 颜色模式也一样,而且没有办法在放大时直接指定颜色模式。可以采用以下办法更改图片颜色模式。

复制代码 代码如下:

Matrix matrix = new Matrix();
float newWidth = 200;       // 图片放大后的宽度
float newHeight = 300;      // 图片放大后的长度
matrix.postScale(newWidth / img.getWidth(), newHeight/ img.getHeight());
Bitmap img1 = Bitmap.createBitmap(img, 0, 0, img.getWidth(), img.getHeight(), matrix, true);// 得到放大图片
img2 = img1.copy(Bitmap.Config.ARGB_4444, false);                           // 得到 ARGB_4444 颜色模式的图片
img = null;
img1 = null;

这里比起本来的图片额外生成了一个图片对象 img1。然则体系会主动收受接管 img1,所以实际内存还是削减了。

归结起来还是以缩略图模式读取图片和削减图片中每个像素占用的内存最为有效。 这两种办法固然有效,然则也有各自的弊病。实际开辟中还是应当按照景象酌情应用。最王道的办法,还是避免垃圾对象的产生。例如在 ListView 的应用中,复用 convertView 等。若是应用 AsyncTask 加载图片,要及时将引用的 ImageView 对象置为 null。因为 AsyncTask 是用线程池实现的,所以此中引用的对象可能会拥有很长的生命周期,造成 GC 无法开释。我还是信赖 Android 的内存收受接管机制的,recycle 什么的固然必然程度上有效,但总感觉不合适 Java 内存收受接管的原则。

 
标签: 图片 内存 优化
反对 0举报 0 评论 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

  • 不得不知道的图片加载框架之Glide
    不得不知道的图片加载框架之Glide
    简介在泰国举行的谷歌开发者论坛上,谷歌为我们介绍了一个名叫 Glide 的图片加载库,作者是bumptech。这个库被广泛的运用在google的开源项目中,包括2014年google I/O大会上发布的官方app。特点(1)使用简单(2)可配置度高,自适应程度高(3)支持常见图片
  • Android Studio(十一):创建可伸缩的图片(9-patch文件)
    Android Studio(十一):创建可伸缩的图片(9-
    Draw 9-patch工具是一个所见即所得编辑器,允许你创建可以自动改变大小来适应视图的内容和屏幕的大小。 以下是使用Draw 9-path工具快速创建一个NinePatch图片。 1、 在命令行中,找到你的sdk/tools目录,运行draw9patch来运行Draw 9-patch工具 2、 拖动你的PN
  • 一个实用方便的图片控件SImageView
    一个实用方便的图片控件SImageView
    控件介绍 这是一个简单到 sImageView.setImageUrls(http://img3.cache.netease.com/ent/2009/4/17/20090417104402666a4.jpg); 设置一个网址即可显示图片的控件相对 ImageView 功能的扩展的控件, 但是没有继承 ImageView 直接继承的 View . 比如 QQ群组头像 ,
  • 第114期:如果你想要开发一个图片 App,Unsplash API 值得你去玩
    第114期:如果你想要开发一个图片 App,Unsplas
    第114期:如果你想要开发一个图片 App,Unsplash API 值得你去玩头条推荐 1、如果你想要开发一个图片 App,Unsplash API 值得你去玩 Unsplash 是一个免费高质量照片的网站,都是真实的摄影照片,照片分辨率也很大,用来做网页素材已经足够,该照片网站每10天
  • Glide、Fresco、Picasso 的背后竟然还有如此强大的图片处理库
    Glide、Fresco、Picasso 的背后竟然还有如此强
    回复 1024 获取更多美女封面图做安卓开发的伙伴儿一定或多或少地都用到过 Image Loader 领域三大领头羊级别的开源库:Glide,Fresco,Picasso。怎么用就不用我在这里啰哩啰嗦了,各自的文档写得非常清楚。今天在[Awesome-Some]里添加了三大 Transformations
    11-10 Fresco
  • 巧用Android图片资源,打造更精致的APP
    巧用Android图片资源,打造更精致的APP
    前言由于android系统的开放性,以及IOS的相对封闭。第三方设备想要使用苹果的OS,目前来说是不可能。所以,各厂商纷纷的投入了android的怀抱, android阵营也越来越强大,如今移动操作系统也就是android和ios的天下。也正是因为android的开放性,可定制度高,
  • Android WebView 实现点击界面图片滑动浏览和保存图片功能
    Android WebView 实现点击界面图片滑动浏览和保
    -文章来源:itsCoder 的 WeeklyBolg 项目 itsCoder主页:http://itscoder.com/ 作者: yongyu0102 审阅者: wuchangfeng 一、概要最近在公司的项目中遇到 需求如下 : 点击 WebView 页面的图片实现开启查看图片模式,即可以显示点击的图片,然后滑动显示下一
    10-31 安卓开发
  • Fresco加载图片封装
    使用第三方库的原则:最好添加一层自己的封装,不要直接使用。防止替换库带来的麻烦!以下是使用Fresco加载图片时的简单封装,以备不时之需。/** * 图片加载的封装 * Created by DevWiki on 2016/8/6. */public class ImageLoader {private static RoundingPa
    10-17 Fresco
  • 简单实现 Android 图片三级缓存机制
    简单实现 Android 图片三级缓存机制
    用户在使用我们的APP时,通常会重复浏览一些图片,这时如果每一次浏览都需要通过网络获取图片,那么将会非常流量。为了节省用户流量,提高图片加载效率,我们通常使用图片三级缓存策略,即通过网络、本地、内存三级缓存图片,来减少不必要的网络交互,避免浪
  • Android WebView图片适配解决方案
    WebView的各种坑,今天又让我发现一个。一、懵逼最近公司项目中新闻模块需要用WebView来加载,而且服务端返回的是String类型的html代码,包含各种标签,各种转义符,一开始直接用loadDataWithBaseURL()加载的时候,出现各种lt;、gt;,直接懵逼了,后面一查,
    10-13 安卓开发
点击排行