- 硬件加速和软件加速的区别
- Canvas与图层
- Bitmap
- 自定义style
硬件加速和软件加速的区别
硬件加速是GPU主导图形绘制
软件绘制是指CPU主导绘制
硬件加速中,由OpenGL调用绘制函数实现绘制,主要优势是提高了Android系统显示和刷新的速度。缺点在于
1、绘制函数被转化成了OpenGL,可能面临OpenGL函数不能完全兼容原生绘制函数的问题
2、需要额外加载OpenGL相关的包,增加内存消耗
3、更加耗电
在Application、activity、window、view中有各自的启用/禁用硬件加速的选项。间《自定义控件入门与实战》P206
Canvas与图层
获取Canvas对象的方法
1、重写onDraw(), dispatchDraw()方法
从传入参数中获取原始Canvas对象,其属于该view。
在绘制流程中,对view来说两个方法都会以同样的先后顺序被调用,除非在ViewGroup中如果缺乏背景onDraw()方法会被跳过。所以,对于图像的绘制代码可以放上述任意方法之中,但通常我们在View中重写onDraw(),在ViewGroup中重写onDisPatchDraw().
2、利用BitMap构建Canvas
Canvas c = new Canvas(bitmap);
通过这个canvas绘制的图像只会保存在bitmap对象中,不会直接显示在界面上,除非我们使用view原始canvas.drawBitmap()方法将该bitmap绘制。
3、使用SurfaceView时候调用其SurfaceHolder.lockCanvas函数
layer, Bitmap, Canvas的关系
layer是透明图层,每次调用canvas.drawXXX方法都会生成一个透明图层来绘制这个图形。
Bitmap是真正承载图像的对象,每次draw一个图形,就是生成一个透明图层绘制图像,然后覆盖到该Bitmap上。Bitmap画布有两种,一种是view的原始画布通过onDraw方法传入,由其中的canvas对象对应,另一种就是人造画布,通过saveLayer(),new Canvas(bitmap)等方法构造。注意saveLayer生成画布后,所有draw函数所生成的图像都是保存在这个新Bitmap中,只有调用resTore,resoreToCount函数后才会返回到原始画布上进行绘制。
Canvas是画布的表现形式,代码中只能通过newCanvas(bitmap)方式生成,可以把Canvas理解成绘图工具,由其函数所绘制的图像最终都是要画到bitmap上的。
保存画布
save()与saveLayer(),保存位置信息和大小信息,对应的flag为MATRIX_SAVE_FLAG,大小信息对应的是CLIP_SAVE_FLAG,可以在调用保存状态函数时候将对应的flag传入。
saveLayer会新建一块画布,后续所有操作都会在这块画布上进行。
恢复画布
restore()与restoreToCount(int count)
两者针对同一个画布栈操作,前者是将栈顶画布出栈,恢复画布状态,后者是一直将栈顶画布出栈直到传入的指定索引画布出栈。
Bitmap
Bitmap是位图,也就是一个个像素点构成的对象。
Android绘制流程中,我们通过重写onDraw方法获得canvas对象去将图像绘制到bitmap中,每个view绑定一个Bitmap,并利用这个Bitmap生成一个Canvas对象,即canvas中保存着一个Bitmap对象,所以该canvas绘制的图像能显示在view上。
总而言之,Bitmap有两种常用方式:
- 通过转化成BitmapDrawbale对象然后转化成Drawable对象作为图像资源使用
Bitmap bitmap = BitmapFactory.decodeResource(res,R.drawable.pdd);
BitmapDrawable bitmapDrawable = new BitmapDrawable();
View view;
ImageView imageView = (ImageView) findViewById(id);
imageView.setImageDrawable(bitmapDrawable);
- 通过绑定Canvas对象用于绘制图像——当做画布
可以通过onDraw,onDispatchDraw方法获得canvas对象然后绘制Bitmap,或者通过new Canvas(bitmap)等方式自建画布。
1、Bitmap格式
用Bitmap.Config标识,推荐ARGB_8888,每个纬度站一个字节,一个像素占四个字节,最占内存同时最清晰
2、Bitmap的存储
在内存中:bitmap是代码生成,其占内存大小为:高宽每个像素占内存大小
在文件中:bitmap是通过压缩算法压缩过的,有不同的压缩格式:JPEG,PNG,WEBP,每种格式对应一种压缩算法。
3、Bitmap的生成
- BitmapFactory生成,
该类可以通过资源,文件,字节数组,FileDescriptor和InputStream等生成Bitmap对象
BitmapFactory.Options可以设置图片的采样率,在不加载图片的前提下获得图片的尺寸信息,通过改变图片的高、宽、缩放比例、是否缩放、像素存储格式等能减少图片像素,实际开发中可以利用该值降低OOM的发生概率。
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = XXX;
String pathName;
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.pdd,options);
imagView.setInmageBitmap(bitmap);
- 利用静态方法构建bitmap
适合裁剪或缩放图片。
public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height);
public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter);
4、Bitmap占用空间的计算
高度(px) * 宽度(px) * 每个像素点的字节数
Android系统会动态缩放bitmap对象。
缩放比例等于:屏幕分辨率/文件所在文件夹的分辨率
eg:xhdpi文件夹(适应480dpi)下原本100px*200px的图片,放在720dpi的真实屏幕下,生成的bitmap对象会被扩大为原来的1.5倍。
多生成的像素是利用类似于setDither的抗抖动算法,利用两个像素生成中间值像素进行填充。
缩小图片同理,减少像素即可,依据inSampleSize采样算法间隔取点即可缩小图片。
- 屏幕分辨率和资源文件夹分辨率适配时候,不会缩放图片;
- 从SD卡等非apk内存获取图片时,不会对图片进行缩放。
5、其他常用函数
- getAllocationByteCount();获取生成的Bitmap的分配空间大小
- recycle()强制回收Bitmap所占用的内存。——Bitmap本身和像素数据都存储在Dalvik堆中。能够被java虚拟机回收。
isRecycle()判断是否已经回收。
在API11以后可以不强制使用回收函数,由GC机制自动处理即可,但如果有大量Bitmap等待GC时候,可能出现卡顿,所以必要时候需要手动回收内存,一般编码如下:
if(bmp != null && !bmp.isRecycled()) {
bmp.recycle();
bitmap = null;
system.gc() //提醒系统及时回收内存
}
- compress()压缩Bitmap
compress(CompressFormat format, int quality, OutputStream stream)
三种压缩格式JPEG,PNG,WEBP,会将bitmap压缩后写入指定的输入流中
6、bitmap、view、drawable、canvas关系
之前已经梳理了大半
canvas内部保存一个Bitmap,view中会新建一个canvas和bitmap,同样表明view也是通过bitmap呈现的,Drawable会利用外部传入的canvas来进行绘制,并且它自己不能保存这个canvas实例。
自定义style
values目录下定义自定义属性,对应自定义控件的布局文件中引用(加上命名空间)或者导入自定义的属性集让xml能够被系统识别,在自定义控件代码中以TypeArray获取对应自定义属性的值(系统无法使用,需要自己加操作方法)
网友评论