屏幕渲染刷新机制

总架构

CPU:负责计算数据,把计算好的数据交给GPU。计算数据指的是View树的绘制过程,也就是Activity对应视图树从根布局DecorView开始遍历View,分别执行测量、布局、绘制三个操作过程
GPU:对图形数据进行渲染,渲染后放到buffer里存起来
display(可称为屏幕或者显示器):负责把buffer里的数据呈现到屏幕上
简单来说就是CPU/GPU准备好数据,存入buffer,Display每隔一段时间去buffer里面取数据,然后显示出来。Display每次读取的频率是固定的,比如16ms一次,但是CPU/GPU写数据是完全无规律的
我们常说的16.6ms刷新一次屏幕其实就是底层以固定的频率将buffer中的屏幕数据显示出来

Activity启动,生命周期方法顺序执行,屏幕渲染流程也开始

  • ActivityThread/handleLaunchActivity/performLaunchActivity/创建activity/调用attach()

Activity.attach/new PhoneWindow/mWindow.setWindowManager/拿到WindowManagerImpl实例,持有phoneWindow的引用/

2件事情:new PhoneWindow实例;和windowManagerService跨进程通讯拿到windowManager实例

  • onCreate()/onStart()
    setContentView
    3件事情:new DecorView;mContentParent=R.id.content; mLayoutInflater.inflate(layoutResID, mContentParent);

  • handleResumeActivity/onResume()
    3件事情:
    在 ActivityThread 中有 handleResumeActivity() 方法
    activity.mDecor = decor
    onresume–setVisible_makeVisible wm.addView(mDecor)—/WindowManagerImpl.addView/WindowManagerGlobal.addView
    root = new ViewRootImpl,root.setView—requestlayout

Android 界面都是activity组件来加载,在activity生命周期方法执行的顺序中,我们实现了view的渲染过程。

每打开一个activity,会new phoneWindow,new DecorView,new ViewRootImpl

  • Activity.onCreate/setContentView/getWindow=phoneWindow/setContentView/new DecorView/FrameLayout—mContentParent=generateLayout(mDecor)/mContentParent.addView/ViewGroup.addView/requestLayout,invalidate()//当mParent=null,不会去执行view绘制//mParent.invalidateChild()

(/ViewRootImpl.invalidateChild/ invalidateChildInParent/checkThread//ViewRootImpl.performTrvaersals)

DecorView 什么时候被添加到 PhoneWindow 上。在 ActivityThread 中有 handleResumeActivity() 方法
activity.mDecor = decor

  • handleResumeActivity/Activity.onResume/把DecorView添加到windowManager,wm.addView(Decor)/WindowManagerImpl.addView/WindowManagerGlobal.addView/初始化

ViewRootImpl,root/ViewRootImpl.setView(view/DecorView),ViewRootImpl持有DecorView的引用/requestLayout(),进行view的绘制流程/view.assignParent(this),将当前ViewRootImpl对象赋值给了DecorView/View.assignParent/给mParent赋值

  • WindowManagerImpl.addView方法/WindowManagerGlobal.addView//参数检查adjustLayoutParams—LayoutParams//初始化ViewRootImpl,把ViewRootImpl赋值给了DecorView.mParent//ViewRootImpl.setView//addToDisplay/WMS的addWindow/分配surface/SurfaceFlinger/把这些Surface混合并绘制到屏幕上

requestLayout和invalidate区别
requestLayout方法会导致View的onMeasure、onLayout、onDraw方法被调用;invalidate方法则只会导致View的onDraw方法被调用

view绘制
CPU
GPU
display

垂直同步信号
ViewRootImpl//view树的顶层
AttachInfo 创建,这个类很重要,之前说的 软解时 Canvas 的保存和复用,还有 View.post() 方法执行等等
TraversalRunnable/doTraversal()/performTraversals()

Add view/requestLayout()

windowManager/WindowManagerGlobal/add、update、remove
Window
View

ViewRootImpl 被 WindowManagerGlobal 创建,
ViewRootImpl 和 Window 的对应关系是多对一,一个 Window 可以有多个 ViewRootImpl

// 调用 windowManager.addView()
wm.addView(decor, l);

root.setView(view, wparams, panelParentView),然后在该方法内部调用requestLayout执行view的三大流程。随后会通过Binder对象WindowSession将Window的添加请求发送给WindowManagerService

https://blog.csdn.net/jiang19921002/article/details/78977560

每一个activity第一次绘制

view有变化刷新

SurfaceFlingger

每一个window都对应一个画/Surface,SurfaceFlingger把各个Surface显示到同一个屏幕上

Android手机屏幕上显示的内容就是由一个个Window组合而成的。顶部的状态栏是一个window,底部的导航栏也是一个window,中间区域也是一个window,toast和dialog也都对应一个自己的window,都由WMS管理。

SurfaceView

首先列举最常见的和View的区别

  • View的绘图效率低,主要用于动画变化较少的程序,必须在主线程更新
  • SurfaceView绘图效率高,用于界面更新频繁的程序,一般在子线程更新
  • SurfaceView拥有独立的Surface(绘图表面),即它不与其宿主窗口共享同一个Surface
  • SurfaceView使用双缓冲机制,播放视频时画面更流畅
  • 每个窗口在SurfaceFlinger服务中都对应有一个Layer,用它来描述它的绘制表面。对于那些具有SurfaceView的窗口来说,每一个SurfaceView在SurfaceFlinger服务中还对应于一个独立的Layer或者LayerBuffer,用来单独描述它的绘图表面,以区别于它的宿主窗口的绘图表面。所以SurfaceView的UI就可以在一个独立的线程中进行绘制,可以不占用主线程资源,它产生原因也是为了应对耗时的操作,例如Camera X。

SurfaceView与View的区别,使用场景

View主要适用于主动更新的情况下,而SurfaceView主要适用于被动更新,比如频繁刷新
View在主线程中对画面进行刷新,SurfaceView通常会通过一个子线程来进行页面的刷新
View在绘图时没有使用双缓冲机制,SurfaceView在底层就已经实现了双缓冲机制

RemoteView在哪些功能中使用

远程访问和控制PC机或者服务器的远程控制软件

题目

  • View的绘制流程分几步,从哪开始?哪个过程结束以后能看到view?

从ViewRoot的performTraversals开始,经过measure,layout,draw 三个流程。draw流程结束以后就可以在屏幕上看到view了。

  • view的测量宽高和实际宽高有区别吗?

多次测量情况下,不一定相等的

实际宽高是在layout流程里确定的

  • view的measureSpec 由谁决定?顶级view呢?

由view自己的layoutParams和父容器一起决定的measureSpec

  • 为什么在activity的生命周期里无法获得测量宽高?有什么方法可以解决这个问题吗?

因为measure的过程和activity的生命周期 没有任何关系。你无法确定在哪个生命周期执行完毕以后 view的measure过程一定走完


//重写activity的这个方法

 public void onWindowFocusChanged(boolean hasFocus) {

 super.onWindowFocusChanged(hasFocus);

 if (hasFocus) {

 int width = tv.getMeasuredWidth();

 int height = tv.getMeasuredHeight();

 Log.v("burning", "width==" + width);

 Log.v("burning", "height==" + height);

 }

 }

  • draw方法 大概有几个步骤?

一共是4个步骤, 绘制背景---------绘制自己--------绘制chrildren----绘制装饰

  • View的绘制过程

一个View要显示在界面上,需要经历一个View树的遍历过程,这个过程又可以分为三个过程,也就是自定义View中的三要素:大小,位置,画什么,即onMesure(),onLayout(),onDraw()。

1.onMesure()确定一个View的大小;

2.onLayout()确定View在父节点上的位置;

3.onDraw()绘制View 的内容;

  • 如何自定义ViewGroup

1.指定的LayoutParams

2.onMeasure中计算所有childView的宽和高,然后根据childView的宽和高,计算自己的宽和高。(当然,如果不是wrap_content,直接使用父ViewGroup传入的计算值即可)

3.onLayout中对所有的childView进行布局。

  • View中onTouch,onTouchEvent,onClick的执行顺序

dispatchTouchEvent—->onTouch—->onTouchEvent—–>onClick。在所有ACTION_UP事件之后才触发onClick点击事件,Onclick 事件是在Up 事件中触发的

  • Onclick 事件的触发条件
    setOnClickListener
    View 没有重写 OnTouchEvent ( 默认情况下 所有触摸事件返回都是clickable,也就是如果View 是可点击的,那么它会消耗一切事件)
    手指没有移动出View的范围。
    有抬起动作

  • 为什么手指移出 View 的范围,不会触发OnClick?
    onTouchEvent ACTION_MOVE动作处理,当pointInView(x, y, mTouchSlop)为false 的时候 ,也就是手指移出View范围,setPressed(false),也就是设置取消了Pressed状态

简述Android的View绘制流程,Android的wrap_content是如何计算的?
https://www.cnblogs.com/duanweishi/p/4301742.html

WindowManager.addView(),View.getParent()是谁?

View 绘制原理会问 requestLayout() 和 invalidate() 什么区别?什么情况下 requestLayout() 会执行 onDraw() 方法?

invalidate、requestlayout是否会调用ondraw?
https://blog.csdn.net/lhl5281/article/details/80136240

#@ 一 是什么,怎么用,为什么

一个UI组件渲染/刷新的流程,细节

学习参考博客

https://www.jianshu.com/p/610cfc29774e//分析ViewRootImpl.setView

http://liuwangshu.cn/tags/WindowManager//刘望舒

https://juejin.im/post/5abd94536fb9a028b92d3c80

https://juejin.im/post/5d260b1c6fb9a07ef4442fb9

https://www.jianshu.com/p/c5d200dde486

https://www.jianshu.com/p/1b12940c55bd

https://juejin.im/entry/59209adc570c350069a54f01

https://juejin.im/entry/56f7eb386be3ff005cfcaaed//Android View 绘制 13 问 13 答

https://blog.csdn.net/Rain_9155/article/details/88829992

Activity界面显示全解析
https://www.jianshu.com/p/65295b2cb047

LayoutInflater#inflate 源码解析
https://www.jianshu.com/p/49fca4c06eff

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值