如果你是画家,有一群人想要看你的画,想象一下整个流程。

  首先找一块画布,执笔,绘制,完成后找一面墙把画挂上去,众人围观。其中不可缺少的要素包括:画布、(画家拿笔)绘制、挂墙展示。对于计算机,也就对应着 帧缓存、像素填充、刷新至屏幕。如果你希望显示一些东西,那么首先你需要拿到一块缓存,然后向这块缓存中填充像素(也就是绘制),然后将这块缓存交给屏幕显示出来。

  Android中的图形绘制,不外如是。

  来看一下典型的绘制-显示代码:

class GameView extends SurfaceView implements Callback{  @Override  public void surfaceCreated(SurfaceHolder holder)  {    Canvas c = holder.lockCanvas();    c.drawBitmap(x, y, bitmap, paint);    holder.unlockCanvasAndPost(c);  }}

  这里先谈谈Canvas,其英文语意为"画布“,一开始天真的我就真把它当成了画布。所谓画布,乃承载画的载体,之于计算机,我的第一反应:画布 = buffer = 缓存,用像素填充画布,然后将它”贴“到屏幕上,就完成了绘制和显示的过程。正是由于我有这个先入为主的观念,按我看来,Canvas应该有个形如Canvas(width, height, PixelType)构造方法,用来生成一块width * height * getBytesOfPerPixel(PixelType) 字节大小的buffer,然后我就可以尽情在上面进行绘制了。但是Canvas最常见的构造方法是Canvas(Bitmap),这曾令我百思不得其解,把一个位图给一块画布,这是什么意思?这个错误的隐喻导致我在看Canvas和Bitmap时纠结了很久。

  事实上,Canvas为一个功能类,提供了大量的drawXXX方法,所以它实际上扮演的是画家的角色,而非画布。要想绘画,你必须给画家一块画布,而Canvas(Bitmap)中的Bitmap则充当了画布的角色。

  再来看上面那个典型的绘制-显示代码:我们需要从中找到绘制(画家和画笔)、缓存(画布)、刷新至屏幕(挂墙展示)这三个基本要素。

  1,绘制

    和一开始的隐喻对应,画家是Canvas,画笔是Paint类的实例paint,Canvas使用paint完成绘制。即代码:c.drawBitmap(x, y, bitmap, paint); 本质是将bitmap绘制(复制)在画布上。

  2, 画布

   来看看画布在哪,Canvas来自于holder.lockCanvas(),这个方法会通过jni调用对应的native方法,其本质是从holder所持有的Surface中获取屏幕冲区的地址,然后用这个地址构造一个native的Bitmap对象(SKBitmap),再用这个Bitmap对象构造一个native的Canvas对象(SKCanvas),再返回这个Canvas对象,java层的Canvas对象其实只是对SKCanvas对象的一个简单包装,所有绘制方法都是转交给SKCanvas来做。

   所以这里的画布就是由屏幕缓存所构造出来的Bitmap。holder.lockCanvas()所返回的Canvas对象是在这块画布上进行绘制。这里的Surface是对屏幕缓存的抽象。我们绘制,可以在屏幕缓存上直接绘制,也可以先绘制在任何一块缓存上,然后将这块缓存中的内容复制到屏幕缓存中。

  值得注意的是,这里你并没有直接获得一块画布(Bitmap),而只是获得了一个画家(Canvas),画家出现的时候手里已经有了画布,不需要你提供给他,就可以进行绘制。

  3,刷新至屏幕

   对应的代码为holder.unlockCanvasAndPost(c),其本质就是将之前绘制好的画布交给图形显示驱动,在真实的设备(屏幕)上显示出来。

 总结:如果你想在Android上进行绘制,你首先要找到一块缓存(Bitmap),然后将其交给画家(构造Canvas),让画家在其上绘制(drawXXX,可能需要提供一只Paint画笔),再将其交给屏幕去显示(本质上是将 所绘制的缓存复制到屏幕缓存中,再触发更新命令,所以你需要找到一个Surface(屏幕缓存),而Android中你无法直接构造Surface,你只能通过SurfaceView或其它方式由系统提供给你一个Surface,而SurfaceView中的Surface是在WindowManagerImpl.addView() - 即添加窗口到WMS时创建的,这个Surface对象为ViewRoot所持有。)

  Andoid中除了用SurfaceView自己来控制屏幕绘制外,对于简单应用,更通常的做法是使用XML指定的View布局,通过框架回调来实现屏幕显示,但其本质和SurvaceView并无区别,同样是 获取缓存、绘制、显示在屏幕,后续将进行分析。


http://www.cnblogs.com/CreateLight/archive/2012/07/04/2575401.html

更多相关文章

  1. 移动围脖Android客户端(用于管理新浪微博)发布
  2. 【移动开发】Android图片异步加载之Android-Universal-Image-Loa
  3. 以 Okhttp3源码 为例 ------ 图解 缓存机制 的原理和实现(上)
  4. Android(安卓)UI绘制优化及建议
  5. [置顶] Android中获取缓存大小和清除缓存功能
  6. Android仿百度加载动画
  7. 关于Android的主流网络请求框架(Okhttp 3 与 RxCache)缓存的那些事
  8. (翻译)API-How Android(安卓)Draws Views
  9. Android(安卓)绘制多个连续带数字圆圈。

随机推荐

  1. Android(安卓)联系人数据库介绍以及对联
  2. [置顶] android开发各种相关干货
  3. PhoneGap是什么?
  4. Android(安卓)混淆
  5. android 设置闹钟及通知
  6. Android(安卓)Studio插件之快速findViewB
  7. requires plug-in org.eclipse.wst.sse.u
  8. Android开源框架----1. SmartImageView图
  9. android Intent练习
  10. 如何解决安卓SDK无法下载Package的问题