Android如何高效显示较大的Bitmaps
一、高效加载较大的Bitmaps
图片有各种形状和各种大小,在很多情况下,图片的实际大小都比图片在应用中所显示的大小要大的多,比如Android系统自带的Gallery 应用显示的照片实际的分辨率通常比手机设备的密度要高很多
考虑到我们是在开发一款内存使用受限的应用,理想的情况下,我们只是想把一个低分辨率版本的位图载入内存,一般来说这个低分辨率版本的位图要跟UI元件实际需要显示的大小相符。一张高分辨率的图片并不会给我们带来任何明显的好处,但却会占用宝贵的内存资源和产生额外的性能开销
二、获取Bitmap的尺寸大小和类型
BitmapFactory类为我们提供了几种decoding方法(decodeByteArray(),decodeFile(),decodeResource(),etc)来从不同的来源创建出Bitmap,如何选择最恰当的decode方法取决于你的图片数据来源,这些方法都会去尝试申请内存来构建Bitmap对象,所有很容易就会导致一个OutOfMemory 异常,每种类型的decode方法都有额外的签名来让你通过BitmapFactory.Options类来指定decoding选项,当我们decoding的时候把inJustDecodeBounds属性设置为true可以避免申请内存,虽然会返回一个nullBitmap对象,但是会为我们传入的BitmapFactory.Options 对象设置outWidth,outHeightandoutMimeType等属性的值,这个技术可以让你在构建Bitmap对象之前事先知道它的大小和类型
BitmapFactory.Optionsoptions=newBitmapFactory.Options(); options.inJustDecodeBounds=true; BitmapFactory.decodeResource(getResources(),R.id.myimage,options); intimageHeight=options.outHeight; intimageWidth=options.outWidth; StringimageType=options.outMimeType;
为了避免java.lang.OutOfMemory 异常,在decodingBitmap之前你有必要去检测Bitmap的大小和类型,除非你真的是非常清楚你要decoding的Bitmap的大小,还有这个大小要适合当前应用内存环境
三、载入‘缩小版'的Bitmap到内存
现在我们已经知道了Bitmap的大小,这将有助于我们来决策是载入整张Bitmap还是载入'缩小版'的Bitmap,这里有一些因素需要进行考虑:
1、载入整张图片预计要使用多少内存
2、在考虑到其它方面内存需要的情况下,你想把多少数量的内存给Bitmap使用:
3、用于显示Bitmap的ImageView控件或其它UI元件的大小
4、当前设备屏幕的大小和密度
例如,一点都不值得载入1024x768 像素的图片到内存中,而最终只在128x96像素大小的ImageView控件上显示
我们应该告诉decoder,图像需要进行抽样,载入一个更小号的Bitmap到内存中,设置BitmapFactory.Options对象的inSampleSize属性为true。例如,一张分辨率为2048x1536像素的图片,如果decode的时候把inSampleSize 设置为4,那么得到的最终图片的大小大约为512x384,载入内存耗费0.75M而不是载入整张时的12M(假设位图的配置为ARGB_8888),下面有一个在目标高和宽基础上计算inSampleSize的方法
publicstaticintcalculateInSampleSize( BitmapFactory.Optionsoptions,intreqWidth,intreqHeight){ //Rawheightandwidthofimage finalintheight=options.outHeight; finalintwidth=options.outWidth; intinSampleSize=1; if(height>reqHeight||width>reqWidth){ if(width>height){ inSampleSize=Math.round((float)height/(float)reqHeight); }else{ inSampleSize=Math.round((float)width/(float)reqWidth); } } returninSampleSize; }
NOTE: inSampleSize 值是2的幂的话,对于decoder来说会更快和更高效。然而,如果你想把调整过大小的位图缓存到内存或硬盘上时,依然非常有意义decoding最合适的位图大小,这样有助于节省内存或节省硬盘空间
下面是一个获取位图的方法
publicstaticBitmapdecodeSampledBitmapFromResource(Resourcesres,intresId, intreqWidth,intreqHeight){ //FirstdecodewithinJustDecodeBounds=truetocheckdimensions finalBitmapFactory.Optionsoptions=newBitmapFactory.Options(); options.inJustDecodeBounds=true; BitmapFactory.decodeResource(res,resId,options); //CalculateinSampleSize options.inSampleSize=calculateInSampleSize(options,reqWidth,reqHeight); //DecodebitmapwithinSampleSizeset options.inJustDecodeBounds=false; returnBitmapFactory.decodeResource(res,resId,options); }
这个方法可以很容易的做到在任意显示尺寸大小的UI元件中去载入一张位图
mImageView.setImageBitmap( decodeSampledBitmapFromResource(getResources(),R.id.myimage,100,100));
在其他的BitmapFactory.decode* 系列的decode方法中以上获取位图的技术也是需要的。
以上就是本文的全部内容,希望对大家学习Android软件编程有所帮助。