App的启动过程(5)ViewTree遍历中最后一步的Draw

来源:互联网 发布:网络招生技巧 编辑:程序博客网 时间:2024/06/04 00:32

以上是WMS端窗口的添加,下面接着ViewTree遍历中最后一步的Draw的分析。

/* ViewRootImpl.java */

private boolean drawSoftware()à canvas =mSurface.lockCanvas(dirty);

View交互的是Canvas,比如drawCanvas cs)参数,应用进程与surfaceflinger交互的是surface,即应用进程端的本地窗口,那么canvassurface之间怎么协作的?

lockCanvas @Surface.java –>nativeLockCanvas@ android_view_Surface.cpp

static jlong nativeLockCanvas((){

//这个是C++层的surface对象

         sp<Surface>surface(reinterpret_cast<Surface *>(nativeObject));

//获取一个存储UI数据的buffer

         ANativeWindow_BufferoutBuffer;

//通过IGraphicBufferProducerdequeuBuffer,获取一个可用的buffer

status_t err =surface->lock(&outBuffer, dirtyRectPtr);

//bitmap分配内存空间,为bitmap分配可用的存储空间

         SkBitmapbitmap;

bitmap.setInfo(info,bpr);

bitmap.setPixels(outBuffer.bits);

//构造本地层的canvas,第二个参数是canvasObjjava层的canvas对象

Canvas*nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvasObj);

//canvas这个作画的工具集设置作画的画纸,也就是bitmap,实际上bitmap的画纸来自于outBuffer,而outBuffer所指向的内存是surface通过lock去申请

nativeCanvas->setBitmap(bitmap);

//返回一个java层的surface

sp<Surface>lockedSurface(surface);

return (jlong)lockedSurface.get();

}

typedef struct ANativeWindow_Buffer {

   // The number of pixels that are show horizontally.

   int32_t width;

   // The number of pixels that are shown vertically.

   int32_t height;

   // The number of *pixels* that a line in the buffer takes in

   // memory.  This may be >=width.

   int32_t stride;

   // The format of the buffer.  Oneof WINDOW_FORMAT_*

   int32_t format;

   // The actual bits.

   void* bits;

   // Do not touch.

   uint32_t reserved[6];

} ANativeWindow_Buffer;

ANativeWindow_Buffer中的属性void*bits就是canvas中作画,存储数据的地方。

 

Surface的职责只是管理SurfaceFlinger分配的用于存储UI数据的内存块,它是一个中介,通过与SurfaceFlinger的协作满足上层的需求。

/* Surface.cpp */

status_t Surface::lock(){

// 当前是否有bufferlocked,因为被Lockedbuffer只能有一个,以mLockedBuffer表示

         if(mLockedBuffer != 0)

//      执行连接到CPU

         interr = Surface::connect(NATIVE_WINDOW_API_CPU);

//设置内存块的用法,

         setUsage(GRALLOC_USAGE_SW_READ_OFTEN| GRALLOC_USAGE_SW_WRITE_OFTEN);

//dequeue一个可用的buffer,是通过GraphicBufferProducer来向BufferQueue获取一个buffer,这里有frontBufferbackBuffer分别代表上一次处理的buffer和当前正在处理的buffer,两次图像更新间通常不需要重绘整个区域,可以借助之前的buffer填充本次的buffer内容,判断是否可以从上一次的buffercopy数据的依据就是buffer的宽、高、格式是否一致。不能copy就要重绘整个界面。

         status_terr = dequeueBuffer(&out, &fenceFd);

//锁定buffer

         status_tres = backBuffer->lockAsync()

}

status_t Surface::unlockAndPost(){

//UI绘制完成,需要解锁,Buffer入队,提交给SurfaceFlinger渲染,SurfaceFlinger后续会这一buffer进行处理,最终显示到屏幕上

         status_terr = mLockedBuffer->unlockAsync(&fd);

         err= queueBuffer(mLockedBuffer.get(), fd);

}

分析了nativecanvas的实现机制,回到java层的performDraw

drawSoftware()@ViewRootImpl.javaà mView.draw(canvas);//同样从viewtree根元素开始

public void draw(){

//View树的根元素开始,逐步往下绘制

         mView.draw(canvas);

}

/*View.java*/

public void draw(Canvas canvas) {

//绘制背景,要考虑是否进行坐标变换

         drawBackground(canvas);

//绘制内容,调用具体子类的onDraw方法

         if(!dirtyOpaque) onDraw(canvas);

//递归绘制子对象,调用ViewGroup子类的实现

         dispatchDraw(canvas);

//scrollbar

         onDrawScrollIndicators(canvas);

         onDrawScrollBars(canvas);

}

onDraw就是具体的绘制,以ImageView为例

onDraw@ImageView.java{

//drawable中内容绘制到这个canvas

         mDrawable.draw(canvas);

}

上面应用进程写完内容后,会解锁这个bufferqueueBuffer,把数据提交:

unlockCanvasAndPost@Surface.java-->unlockAndPost@Surface.cpp

在把这个buffer入队,即queuebuffer时,queueBuffer@BufferQueueProducer.cpp这个方法中,会通过sp<IConsumerListener>frameAvailableListener这个监听,把当前有可消费的buffer的这个事件通过onFrameAvailable发出去,这样buffer的消费者就会取这个buffer

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 公司老板跑路了社保怎么办 公司老板跑路社保怎么办 公司被公安局查封社保怎么办 小米四开不了机怎么办 小米的手机后壳裂了怎么办 公司没钱拖欠员工社保怎么办 小米note充不进去电怎么办 公司欠社保没交怎么办 公司不给转社保怎么办 小米note充电特别慢怎么办 小米小米note2充电慢怎么办 小米note充电红灯不闪烁怎么办 小米note充电红灯闪烁怎么办 小米note2突然充电慢怎么办 充电小米note2手机闪烁怎么办 小米6x上网慢怎么办 小米5数据上网慢怎么办 小米5c照相模糊怎么办 小米5充电很慢怎么办 iphone图库照片没了怎么办 我想通过微信号得到手机号怎么办 给充电宝充电慢怎么办 小米5s充不了电怎么办 百度网盘下载速度慢怎么办 负债累累没有钱没有资源怎么办 好福利密码忘了怎么办 手机无法申请百度网盘怎么办 魅族手机运行慢怎么办 阿里小宝卡流量用完了怎么办 阿里宝卡流量用完了怎么办 百度网盘本地空间不足怎么办 百度网盘空间不足怎么办 百度网盘容量不够怎么办 百度网盘内存不够怎么办 百度网盘储存空间不足怎么办 百度网盘手机号注销了怎么办 手机系统升级后照片没了怎么办 换手机照片没了怎么办 苹果手机icloud满了怎么办 百度网盘密码忘记怎么办 手机卡不用了支付宝账号怎么办