ImageView设置图片的优化

ImageView设置图片的方式有很多钟,可以在xml里面写android:src=”@drawable/xxx”,也可以在java代码里面设置。

在java里面的设置方式也有多种,方法包括:setImageResource,setImageDrawable,setImageBitmap。

在xml里面设置实际上和在java里面调用setImageResource是一样的,当然xml多了一个解析的过程,放到java代码里调用会稍微好些(实际没什么区别)。

3种设置图片方式的区别:

(1)setImageResource的参数是resId,必须是drawable目录下的资源.另外,在setImageResource方法中有写明了注释

* <pclass="note">This does Bitmap reading and decoding on the UI

* thread, which can cause a latency hiccup.If that's a concern,

* consider using {@link #setImageDrawable(android.graphics.drawable.Drawable)}or

* {@link #setImageBitmap(android.graphics.Bitmap)} and

* {@link android.graphics.BitmapFactory} instead.</p>

setImageResource 是从资源drawable中通过资源id找到文件转成可绘制对象drawable 然后绘制。这个方法会自动适配分辨率。适用于不频繁设置图片图片资源不会太大的情况。 但是对于大图片时或者你需要不断的重复的设置图片 调用这个方法生成的drawable里一样会生成一个bitmap对象 因为bitmap是通过bitmapfactory生成的 有一部分要调用C库所以需要开辟一部分native本地内存空间以及一部分jvm的内存空间。而native本地内存空间是C开辟的 jvm的gc垃圾回收器是回收不了这部分空间的,这个时候如果你频繁的调用setImageResource且没有手动调recycle native的内存空间很难被释放掉。jvm的内存也不会及时得到回收这样就相当容易导致内存溢出。

这个方法是在UI线程中对图片读取和解析的,所以有可能对一个Activity的启动造成延迟,而且占空间,资源不会及时回收,图片多且大运行很容易出outofmemory的错误。所以如果顾虑到这个官方建议用setImageDrawable和setImageBitmap来代替。

(2)setImageBitmap参数是Bitmap,可以解析不同来源的图片再进行设置。不过我们看看setImageBitmap的源码:

@android.view.RemotableViewMethod

public void setImageBitmap(Bitmap bm) {

// if this is used frequently, mayhandle bitmaps explicitly

// to reduce the intermediate drawable object

setImageDrawable(newBitmapDrawable(mContext.getResources(), bm));

}

setImageBitmap 当你需要频繁设置大图片时 通过bitmapfactory生成bitmap然后设置 然后每次设置前将之前的bitmap手动掉recycle 置为可回收状态 这样很大程度能防止内存泄露溢出

实际上setImageBitmap做的事情就是把Bitmap对象封装成Drawable对象,然后调用setImageDrawable来设置图片。因此代码里面才写上了建议,如果需要频繁调用这个方法的话最好自己封装个固定的Drawable对象,直接调用setImageDrawable,这样可以减少Drawable对象。因为每次调用setImageBitmap方法都会对Bitmap对象new出一个Drawable。

你的图片是不频繁设置且不会太大就用第一种 如果需求不断的重复更新设置那最好用第二个并且记住手动及时回收后再设置 如果有用到图片缓存的话则不要将大图片列入缓存中  图片的缓存模块最好只存储小且利用频繁的图片以节省内存和时间开销 大图则需做手动回收 以保证低端点的机子不会oom

 

(3)setImageDrawable参数是Drawable,也是可以接受不同来源的图片,方法中所做的事情就是更新ImageView的图片。上面两个方法实际上最后调用的都是setImageDrawable(setImageResource没有直接调用,不过更新的方法与setImageDrawable一样)。

所以综合来看setImageDrawable是最省内存高效的,如果担心图片过大或者图片过多影响内存和加载效率,可以自己解析图片然后通过调用setImageDrawable方法进行设置。

 

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

* @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. Bitmap bitmap = readBitmap(this,R.drawable.a);  

2. Drawable drawable = new BitmapDrawable(bitmap);  

3. Bitmap previousbitmap = previousImage.getDrawingCache();  

4. if(previousbitmap != null && !previousbitmap.isRecycled())  

5.     previousbitmap.Recycle();  

6. previousImage.setImageDrawable(drawable);  

 

/**

 * 释放ImageView里的图片,防止加载过多内存溢出

 * @param imageView

 */

public static void releaseImageViewResouce(ImageView imageView) {

if (imageView == null)

return;

Drawable drawable = imageView.getDrawable();

imageView.setImageDrawable(null);

imageView.setBackgroundDrawable(null);

if (drawable != null)

drawable.setCallback(null);

if (drawable != null && drawable instanceof BitmapDrawable) {

BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;

Bitmap bitmap = bitmapDrawable.getBitmap();

if (bitmap != null && !bitmap.isRecycled()) {

// bitmap.recycle();

bitmap = null;

}

}

imageView = null;

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值