Bitmap使用分享

来源:互联网 发布:linux如何安装xz 编辑:程序博客网 时间:2024/06/08 05:34
这篇文章里面只是想总结一下工作中使用Bitmap遇到的一些使用情况。
Bitmap翻译过来就是"位图",对于Bitmap更多的优化问题吧!

一、Bitmap的回收
Bitmap类有一个方法recycle(),从方法名可以看出是回收的意思。虽然有GC,但是有时候回收还是不尽如人意,这时候我们就需要用到recycle()我们手动来释放bitmap的内存。
 public void recycle() {
        if (!mRecycled) {
            if (nativeRecycle(mNativeBitmap)) {
                mBuffer = null;
                mNinePatchChunk = null;
            }
            mRecycled = true;
        }
    }
boolean mRecycled:是否被回收
使用了JNI方法回收bitmap,nativeRecycle(mNativeBitmap)的返回值表示原生像素对象是否实际回收。false表示它在native仍然在使用和这些对象现在不应该收集。当位图本身被收集它们将被收集后。

一般来说,如果能够获得Bitmap对象的引用,就需要及时的调用Bitmap的recycle()方法来释放Bitmap占用的内存空间,而不要等Android系统来进行释放。

下面是释放Bitmap的示例代码片段。

// 先判断是否已经回收

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

        bitmap.recycle(); 

在bitmap不再需要的时候就可以进行回收了


二,Bitmap的创建

Bitmap类的构造方法都是私有的,所以开发者不能直接new出一个Bitmap对象

一种是方式是使用BitmapFactory

先说用IO流创建吧

InputStream is = res.openRawResource(R.drawable.welcome);  // 读取资源文件获取输入流 

//当然上面的IO流也可以是网络获取的,而BitmapFactory.Options options的使用

Bitmap bitmap = BitmapFactory.decodeStream(is);//创建bitmap

但是当我们遇到一些大图的时候就是出现OOM了,所以BitmapFactory提供了另一个方法

decodeStream(InputStream is, Rect outPadding, Options opts)

这个Options是BitmapFactory的一个内部类,修改Options的一些属性可以帮助我们优化加载bitmap是的内存,示例代码如下:

//实例化BitmapFactory.Options

BitmapFactory.Options options = new BitmapFactory.Options();
options .inPreferredConfig = Bitmap.Config.RGB_565;
options .inPurgeable = true;
options .inInputShareable = true;
//创建bitmap
Bitmap bitmap = BitmapFactory.decodeStream(is, null, options);
其中inPreferredConfig是这是bitmap的每一个像素所占的位的配置,而Bitmap.Config的配置有四种:
Bitmap.Config.ALPHA_8 代表8位Alpha图(至于什么Alpha自己找)
Bitmap.Config.ARGB_4444 代表16位ARGB(ARGB各占4位)
Bitmap.Config.ARGB_8888 代表32位ARGB(ARGB各占8位)
Bitmap.Config.RGB_565 代表16位RGB(R占5位,G占6位,B占5位)
另外两个属性需要共同设置,inPurgeable和inInputShareable属性我查看过Api但是没有看的太明白,如果有明白的大神还请告诉一下。

还有一种是使用Bitmap的createBitmap(),这个方法有一系列的方法都能够创建bitmap,可能有人会很奇怪的问到为什么会用到这个一系列的方法,那是在开发的时候遇到问题了,我需要根据ScrollView的滑动去改变一个圆角背景图的颜色。可能大家都会去写一个drawable文件来搞定圆角,但是颜色没办法动态改变啊!于是就想到自己去创建一个bitmap,然后自己把它在切圆。找了一会找到这个方法Bitmap.createBitmap(int width, int height, Bitmap.Config config),可以生成一个指定宽高的bitmap,后面的Bitmap.Config就是之前提到的位图像素位配置。
但是这样得到的bitmap是一个有宽高,没有仍和显示,因为还没有个bitmap上的每一个像素设置颜色,那挨个像素去设置这个想法应该不会有人去实现吧!于是就用用到的Canvas(画布)。
Bitmap bitmap = Bitmap.createBitmap(width,height,Config.ARGB_4444);
Canvas canvas =  new Canvas(bitmap);//构造一个画布来绘制bitmap
canvas.drawARGB(255, 255, 255, 255);//设置绘制的颜色
canvas.drawBitmap(newb, 0, 0, null); //显示在bitmap上
这样bitmap就有颜色了,只差切圆角了;其实圆角可以在上面创建的那个过程就一并完成的,但是由于没有自习学习没有去合并代码,这里只是提供一中参考。

三、Bitmap的压缩
在上传图片的时候使用过这个方法
Bitmap的compress(CompressFormat format, int quality, OutputStream stream)可以按指定的图片格式以及画质,将图片转换为输出流。 
format:Bitmap.CompressFormat.PNG或Bitmap.CompressFormat.JPEG 
quality:画质,0-100.0表示最低画质压缩,100以最高画质压缩。对于PNG等无损格式的图片,会忽略此项设置。 

如果图片像素过大,比如浏览照片。可能我们就需要生成缩略图来优化,以减少载入图片过程中的内存的使用,避免发生OutOfMemory异常。
使用BitmapFactory.Options中inSampleSize就可以缩小图片。该属性表示缩略图大小为原始图片大小的几分之一。例如设置inSampleSize=2,则取出的缩略图的宽和高都是原图片的1/2,图片的大小就为原图大小的1/4。
那可能就会问:“如何能知道图片过大呢?”
我们可以默认对所有图片都进行这中处理,但是有些图没有必要进行压缩形成缩略图的意义不大,还影响用户体验了。
于是我们可以通过设置BitmapFactory.Options的inJustDecodeBounds=true之后,再使用上文中提到过的BitmapFactory.decodeStream(is, null, options)等方法之后,我们就能在options中获取到图片的原始宽高了,即options.outWidth和options.outHeight。对这两个值进行判断就可以知道图片是否过大了。
值得注意的是inJustDecodeBounds=true的时候执行decodeStream方法并不会真正的分配空间,这时候获取到的bitmap为null,所以这里不用担心会OOM。
示例代码:
BitmapFactory.Options options= new BitmapFactory.Options();
options.inJustDecodeBounds = true;// 设置inJustDecodeBounds为true
BitmapFactory.decodeStream(is, null, options);// 使用decodeFile方法得到图片的宽和高
int width = options.outWidth;
int height = options.outHeight;

在实际项目中可以利用上面的代码,先获取图片真实的宽度和高度,然后判断是否需要缩小。
如果不需要缩小,设置inSampleSize的值为1。
如果需要缩小,则动态计算并设置inSampleSize的值,对图片进行缩小。
这里有一点需要注意,在下次使用BitmapFactory的decodeStream()等方法实例化Bitmap对象前,必须要将options.inJustDecodeBound设置为false,否则创建的bitmap为null。
为什么这里我举例的是类似与相册的使用呢?因为通过联网获取的图片我们可以在程序中进行压缩和优化,同时服务端也可以根据不同的手机分辨率返回不同的大小的图片来优化。

总结:
这是我在开发过程中遇到的一些问题肯定不是很全面,在这里分享一下,有错误还请大家指正!!
还有一点值得说的是,即使已经优化的很好的,但是我们还是一定要捕获Exception或Error,避免程序Crash。





0 0
原创粉丝点击