Android Render(一)Activity窗口构成和制图解析


阅读者三篇Android绘制小说,会让您对驾驭Android绘制有帮衬:


壹、Activity窗口构成

此地我们会介绍到ActivityPhoneWindowDecorViewViewRootImplWindowManagerImplWindowManagerGlobalActivityThreadSurface,关于Activity窗口有为数不少上边可讲,作者那边只侧重于Activity窗口的Render方面来讲课。先来两张张大家早已经烂熟于心的图:

一-一 Activity开发银行流程图

1-2 Activity构成图

三个Activity的结缘有,ActivityPhoneWindowDecorView,再加上DecorView里面包车型大巴TitleBar和大家填充的content内容,那几个还Activity构成须求的具体类,不是部分支持类,其实还有ViewRootImplWindowManagerImplWindowManagerGlobalActivityThread那多少个不可知的协助类,就算是Activity构成可知UI界面没用到,但是那多少个帮衬类都以直接大概直接承担了Activity的营造和制图的。上边笔者遵照本身的领会来所有人家介绍那个类的效应和被创设时机,有畸形的地点还请我们指正:

  • Activity:八个持续ContextThemeWrapper的类,承接自ContextThemeWrapper那么意味着,通过Activity能够访问当前包的财富(getResources、getAssets)和运营别的零件(Activity、Service、布Rhodescast)以及获得各类劳动(getSystemService),并且定义了方今Activity的Theme主旨项目
    ,关于Context的讲授请看:http://www.cnblogs.com/android100/p/Android-Context.html
    再正是只有创设了叁个Activity才会成立后边的PhoneWindow、DecorView、ViewRootImpl、WindowManagerImpl、和Surface那个类。笔者那边并没说ActivityThread类,ActivityThread是Android应用的主线程(UI线程),四个采取进度才有一个UI线程。也未尝说WindowManagerGlobal类,这一个类用了多少个数组管理2个运用进程内享有Activity的DecorView和ViewRootImpl以及WindowManager对应提到的。WindowManagerGlobal是二个单例的类,一个应用进度内也唯有一个。可是WindowManagerImpl是每3个Activity都有1个的。Activity是在ActivityThread的performLaunchActivity方法中用ClassLoader类加载器创设出来的。

  • PhoneWindow:
    一个一连于肤浅类Window的类,也是Window的唯一兑现类。在Activity中PhoneWindow处在甲级地点,然而PhoneWindow是四个不可知的类,PhoneWindow内的DecorView才是我们可知的UI布局,不过大家可知的UI布局为何要卷入一层PhoneWindow列?经过自家的往往查看源代码和推敲,小编发现PhoneWindow肩负了Activity
    UI分界面一流布局DecorView的创设,PhoneWindow保存了window
    attributes即窗口布局属性参数,保存了与WindowManagerService进度通信的IBinder
    (取名token)方便去系统WindowManagerService进度通信,并且负责了用户Key和Touch事件的散发,然而PhoneWindow分发事件也是提交了DecorView来完成的。除了大家Activity在setContent时PhoneWindow创设了DecorView,好像PhoneWindow并从未负担太多的Render的事件。看源码确实正是那般啊!,其实真正的Render操作都在ViewRootImpl类中。PhoneWindow是在Activity的attach方法中new出来的。

  • WindowManagerImpl:
    见名知意,正是管制Window的,在那里正是管制PhoneWindow的,每一个Activity都有一个温馨的WindowManagerImpl来管理自个儿的PhoneWindow,WindowManagerImpl其实是用来治本PhoneWindow里面的DecorView的,也说不定是DecorView级其余别样的View,还有便是WindowManagerImpl是用来跟2个App全局的PhoneWindow管理器WindowManagerGlobal通信的,加多、移除和更新DecorView层级的View时WindowManagerImpl会调用WindowManagerGlobal中的方法来举行全局管理。WindowManagerImpl是在Activity的attach方法中new
    PhoneWindow后调用mWindow.setWindowManager方法成立的,其内部是调用setWindowManager的createLocalWindowManager方法new出来的。

  • DecorView:
    是三个ViewGroup,承接自FrameLayout,是我们看来的UI分界面包车型地铁头等容器,DecorView是PhoneWindow的积极分子。DecorView除去是Activity界面包车型客车一等容器以外,DecorView依然key和touch事件从上向下真正分发开头的源流。事件分发从Activity—》PhoneWindow—》DecorView—》层层向下分发到我们的界面底层。DecorView其实在广大地点都会创建,PhoneWindow内部的getDecorView方法被调用时,固然当中的积极分子变量mDecor为空的话,就会调用installDecor()方法去创立贰个DecorView,最后new
    贰个DecorView重返,保障调用PhoneWindow的getDecorView获取
    DecorView时永远不会为空。
    自家看代码发现PhoneWindow的DecorView第1回调用发生在ActivityThread内的handleResumeActivity方法中,handleResumeActivity方法中还有三个很重大的步子,正是调用了WindowManagerImpl的addView(DecorView,WindowManager.LayoutParams
    )方法,进去创造了三个跟DecorView关联的ViewRootImpl类。

  • ViewRootImpl:是一个落到实处了ViewParent接口的final类。作者后边聊到了,ViewRootImpl重要是肩负Activity的分界面Render绘制的,负责整个窗口分界面包车型地铁ViewTree的绘图更新。ViewRootImpl要肩负DecorView的绘图,那么ViewRootImpl就要求全体当前Activity的DecorView的引用,是的,的确如此,后面介绍DecorView的创导的时候本人提及了DecorView第二次成立发生在ActivityThread内的handleResumeActivity方法中,handleResumeActivity方法中还有三个很要紧的步调,正是调用了WindowManagerImpl的addView(DecorView,WindowManager.LayoutParams
    )方法,进去创立了2个跟DecorView关联的ViewRootImpl类。WindowManagerImpl的addView方法其实调用了WindowManagerGlobal的addView方法,在这些主意中开创了ViewRootImpl,并且在这些措施中调用了ViewRootImpl的setView方法,使ViewRootImpl持有DecorView的引用。并且把贯彻了ViewParent接口的和谐设置成了DecorView的Parent。这样ViewRootImpl就能够胡作非为地操作DecorView了。其实我在调用普通view的invalidate()刷新时,其实是透过层层Parent搜索,最终调用了最顶层的ParentViewRootImpl的invalidate()来判别和拍卖每一次的UI分界面刷新的。

  • Surface:二个落到实处了Parcelable接口的类,对Parcelable接口不打听的,请看作者事先的Binder通讯的文章:Android
    IPC之AIDL看那1篇还不够
    Surface是固有图像缓冲区(raw
    buffer)的3个句柄,而原来图像缓冲区是由荧屏图像合成器(screen
    compositor)管理的。获得了Surface其一句柄就足以获得在这之中的Canvas、原生缓冲器以及别的方面包车型地铁始末。所以说Surface是生成Canvas的地方,具体正是调用lockCanvas方法获得Canvas。至于Canvas、Paint
    和Bitmap的关联作者那边就不讲了,前边会有作品来讲这一个。Surface是ViewRootImpl的多少个final成员变量,伴随ViewRootImpl的成立暗许就new一个出来了,不过此时的Surface是3个空的,里面是尚未内容的。Surface的数额填充是要跟WindowManagerService相互的,应用进度端Binder布告WindowManagerService进度端创制贰个Surface对象,最终是将WindowManagerService进度端的
    Surface对象传递到使用进度端并赋值给使用进度的Surface对象,那样窗口能够选择Surface来绘制UI了。
    因为Surface对象要夸进度传递,所以Surface要落到实处Parcelable接口。更详实的牵线有关窗口的Surface成立请看锤子科学和技术创办者罗永浩的:Android应用程序窗口(Activity)的绘图表面(Surface)的创建进程分析

二、Activity窗口创制流程

地点的名词介绍其实就是坚守窗口的始建流程的依次来讲的,可是单单是文字不够直观,上边以箭头加方法名的款式显示一下,源码分析流程基于Android7.一

/**1*/ ApplicationThread的onTransact方法接收到SystemServer进程的SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION启动Activity的Binder信息
                ↓
/**2*/ ApplicationThread.scheduleLaunchActivity() //
                ↓
/**3*/ ActivityThread.scheduleLaunchActivity() //安排启动Activity
                ↓
/**4*/ ActivityThread.handleLaunchActivity()  //处理启动Activity
                ↓
/**5*/ ActivityThread.handleResumeActivity() // Activity 的Resume会使DecorView跟ViewRootImpl关联
                ↓
/**6*/ WindowManagerGlobal.addView() //全局保存窗口的信息
                ↓
/**7*/ ViewRootImpl.setView()  //使DecorView和ViewRootImpl关联并绘制界面
                ↓
/**8*/ ViewRootImpl.requestLayout() //请求绘制ViewTree
                ↓
/**9*/ ViewRootImpl.scheduleTraversals() // 安排遍历 
                ↓
/**10*/ ViewRootImpl.doTraversal() //
                ↓
/**11*/ ViewRootImpl.performTraversals() //执行遍历 会根据情况调用relayoutWindow performMeasure performLayout performDraw 等方法 这四个方法跟绘制是紧密相关的
                ↓
/**12*/ ViewRootImpl.relayoutWindow() //窗口第一次创建或者是窗口大小有变化并且窗口可见就会调用此方法 
                ↓
/**13*/ ViewRootImpl.mWindowSession.relayout() //binder通信通知WindowManagerService创建一个跟应用端关联的Surface
                ↓
/**14*/ ViewRootImpl调用performMeasure performLayout performDraw方法绘制UI

事实上第六步ActivityThread.handleResumeActivity()方法内会调用到WindowManagerGlobal.addView()方法把窗口绘制完毕,紧接着就调用到了activity.makeVisible()方法,其实便是显得出DecorView,因为DecorView创立绘制前是被设置成了INVISIBLE的,Activity中的makeVisible方法正是把绘制完成的DecorView展现出来了:

    void makeVisible() {
        if (!mWindowAdded) {
            ViewManager wm = getWindowManager();
            wm.addView(mDecor, getWindow().getAttributes());
            mWindowAdded = true;
        }
        mDecor.setVisibility(View.VISIBLE); //把DecorView设置成可见的
    }

于今大家就见到Activity分界面上的UI了。

有关Activity的绘图表面(Surface)的创导进程本人还想多说一下,以及Surface跟Activity的呼应关系。

Surface是ViewRootImpl的贰个final成员变量,伴随ViewRootImpl的创办暗中同意就new3个出来了,不过此时的Surface是1个空的,里面是不曾内容的。Surface的数据填充是要跟WindowManagerService相互的,应用进度端Binder布告WindowManagerService进度端创造一个Surface对象,最后是将WindowManagerService进度端的
Surface对象传递到利用进度端并赋值给使用进度的Surface对象,那样窗口能够采纳Surface来绘制UI了。
因为Surface对象要夸进度传递,所以Surface要完结Parcelable接口。

从Activity窗口成立的流程大家得以知晓:

  • 每二个应用程序窗口都对应该八个Java层的Surface对象,当中三个是在WindowManagerService劳动那旁边开立的,而别的2个是在应用程序进程这旁边创造的。

  • 在WindowManagerService服务那旁边创办的Java层的Surface对象在C++层关联有多个SurfaceControl指标,用来设置使用窗口的习性,例如,大小和职位等。

  • 在应用程序过程那旁边开立的ava层的Surface对象在C++层关联有一个Surface对象,用来绘制应用程序窗品的UI。

3、Activity窗口组件之间的照应关系

三个配备有二个WindowManagerService进程 有一个SystemServer进程

一个App有一个WindowManagerGlobal类 有一个ActivityThread类
有一个ApplicationThread类

一个App能够有不计其数个Activity

一个 Activity有一个PhoneWindow类

一个PhoneWindow类有一个ViewRootImpl类

一个PhoneWindow类有一个WindowManagerImpl类

一个ViewRootImpl类有一个Surface类C++, 有一个DecorView类

用一张图表示:

Android设备构成图

参考文章:
Android应用程序窗口(Activity)的绘图表面(Surface)的创始进度分析
从源码看invalidate和requestLayout的分别
Android
Render类别规划篇

Android应用层View绘制流程与源码分析