Framework定义了客户端组件和服务器端组件功能及接口,包含3个部分:服务端、客户端和linux驱动,以下图所示: linux
Framework中所包含的服务是很是多的,为了清晰的描述服务端、客户端和linux驱动三者的关系,咱们只是描述了它们其中的一小部分,这一小部分也是为后续讲解窗口的建立、Activity启动、绘制、事件分发服务的。程序员
服务端主要包含两个重要类,分别是WindowManagerService(WMS)和ActivityManagerService(AMS):api
除此以外,在服务端还包括2个信息处理类:服务器
客户端主要包括如下重要类:框架
ActivityThread类
该类为应用程序的主线程类,全部的APK程序有且只有一个ActivityThread类,程序的入口为该类中的static main()函数,ActivityThread所在的线程即为ui线程或主线程。异步
Activity类
该类为APK程序的一个最小运行单位,一个apk程序中能够包含多个activity对象,activityThread主类会根据用户操做选择运行哪一个activity对象。函数
PhoneWindow类
该类继承与Window类,同时phonewindow类内部包含了一个decorView对象,简而言之,PhoneWindow是把一个FrameLayout进行了必定的包装,并提供了一组通用的窗口操做接口。oop
Window类
该类是一组通用的窗口window操做api,这里的窗口仅仅是程序层面上的,wms所管理的窗口并非window类,而是一个view或者viewgroup类,通常就是指DecorView类,即一个D而从容View就是wms全部管理的一个窗口,window是一个abstact类型。ui
DecorView类
该类是一个FrameLayout的子类,而且是PhoneWindow的一个内部类,DecorView就是对普通的FrameLayout进行了必定的修饰,好比添加一个通用的TitleBar,并响应特定的按钮消息等。spa
ViewRoot类
Wms管理客户端窗口时,须要通知客户端进行某种操做,这些都是经过IPC调用完成的,而在客户端窗口收到IPC调用后,都会把该调用转换为本地的一个异步调用,实现方式就是使用handler,ViewRoot就是继承与handler,其主要做用就是就接手wms的IPC调用转换为本地的一个异步调用。
w类
该类继承于Binder,而且是一个viewRoot的一个内部类。WMS通知客户端窗口时,是经过IPC调用,也就是调用该Binder类,而后该Binder内部的处理函数通常会给该类所在的ViewRoot类发送一个Handler消息,以便进行异常处理。
windowManager类
客户端要申请建立一个窗口,而具体建立窗口的任务是有wms完成的,windowManager类就像是一个部门经理,谁有什么需求就告诉他,由它和wms进行交互,客户端不能直接和wms进行交互。
Linux驱动和Framework相关的主要包含两个部分,分别是surfaceFlingger和Binder,每个窗口都对应一个Surface,sf驱动的做用就是把各个surface显示在同一个屏幕上。
Binder驱动的做用是提供框进程 ipc 的消息传递机制。
下图是一个更加完成的APK程序工做的流图:
而后建立一个ActivityThread对象,在ActivityThread的初始化代码中会建立一个H(Handler)对象和一个ApplicationThread(Binder)对象。其中Binder负责接收远程AmS的IPC调用,接收到调用后,则经过Handler把消息发送到消息队列,UI主线程会异步地从消息队列中取出消息并执行相应操做,好比start、stop、pause等。
接着UI主线程调用Looper.loop()方法进入消息循环体,进入后就会不断地从消息队列中读取并处理消息。
当ActivityThread接收到AmS发送start某个Activity后,就会建立指定的Activity对象。Activity又会建立PhoneWindow类→DecorView类→建立相应的View或者ViewGroup。建立完成后,Activity须要把建立好的界面显示到屏幕上,因而调用WindowManager类,后者因而建立一个ViewRoot对象,该对象实际上建立了ViewRoot类和W类,建立ViewRoot对象后,WindowManager再调用WmS提供的远程接口完成添加一个窗口并显示到屏幕上。
接下来,用户开始在程序界面上操做。KeyQ线程不断把用户消息存储到QueueEvent队列中,InputDispatcherThread线程逐个取出消息,而后调用WmS中的相应函数处理该消息。当WmS发现该消息属于客户端某个窗口时,就会调用相应窗口的W接口。
W类是一个Binder,负责接收Wms的IPC调用,并把调用消息传递给ViewRoot,ViewRoot再把消息传递给UI线程ActivityThread,ActivityThread解析该消息并作相应的处理。在客户端程序中,首先处理消息的是DecorView,若是DecorView不想处理某个消息,则能够将该消息传递给其内部包含的子View或ViewGroup,若是尚未处理,则传递给PhoneWindow,最后再传递给Activity。
在多任务操做系统中,任何程序都运行在线程之中。系统首先会为客户端程序分配一个线程,而后该线程从程序的入口处开始执行。那么,请思考如下问题。
首先,很明确地讲,包含有Activity的客户端程序至少包含三个线程,如图6-1所示。每一个Binder对象都对应一个线程,Activity启动后会建立一个ViewRoot.W对象,同时ActivityThread会建立一个ApplicationThread对象,这两个对象都继承于Binder,所以会启动两个线程,负责接收Linux Binder驱动发送IPC调用。最后一个主要线程也就是程序自己所在的线程,也叫作用户交互(UI)线程,由于全部的处理用户消息,以及绘制界面的工做都在该线程中完成。
自定义Thread和UI线程的区别在于,UI线程是从ActivityThread运行的,在该类中的main()方法中,已经使用Looper.prepareMainLooper()为该线程添加了Looper对象,即已经为该线程建立了消息队列(MessageQueue),所以,程序员才能够在Activity中定义Handler对象(由于声明Handler对象时,所在的线程必须已经建立了MessageQueue)。而普通的自定义Thread是一个裸线程,所以,不能直接在Thread中定义Handler对象,从使用场景的角度讲,即不能直接给Thread对象发消息,可是却能够给UI线程发消息。