`

Android Framework内核之旅

 
阅读更多

Framework框架

Framework 定义了客户端 组件和服务端组件功能及接口。以下阐述中,“应用程序”一般是指“ .apk ”程序。

框架中包含三个主要部分,分别为服务端、客户端和 Linux 驱动。

6.1.1
服务端

服务端主要包含两个重要类,分别是 WindowManagerService WmS )和 ActivityManagerService
(AmS)
WmS 的作用是为所有的应用程序分配窗口,并管理这些窗口。包括分配窗口的大小,调节各窗口的叠放次序,隐藏或者显示窗口。 AmS 的作用是管理所有应用程序中的 Activity

除此之外,在服务端还包括两个消息处理类。

—
KeyQ 类:该类为 WmS 的内部类,继承于 KeyInputQueue 类, KeyQ 对象一旦创建,就立即启动一个线程,该线程会不断地读取用户的 UI 操作消息,比如按键、触摸屏、 trackball 、鼠标等,并把这些消息放到一个消息队列 QueueEvent 类中。

—
InputDispatcherThread 类:该类的对象一旦创建,也会立即启动一个线程,该线程会不断地从 QueueEvent 中取出用户消息,并进行一定的过滤,过滤后,再将这些消息发送给当前活动的客户端程序中。

6.1.2
客户端

客户端主要包括以下重要类。

—
ActivityThread 类:该类为应用程序的主线程类,所有的 APK 程序都有且仅有一个 ActivityThread 类,程序的入口为该类中的 static main() 函数。

—
Activity 类:该类为 APK 程序的一个最小运行单元,一个 APK 程序中可以包含 Activity 对象, ActivityThread 主类会根据用户操作选择运行哪个 Activity 对象。

—
PhoneWindow 类:该类继承于 Window 类,同时, PhoneWindow 类内部包含了一个 DecorView 对象。简而言之, PhoneWindow 是把一个 FrameLayout 进行了一定的包装,并提供了一组通用的窗口操作接口。

—
Window 类:该类提供了一组通用的窗口( Window )操作 API ,这里的窗口仅仅是程序层面上的, WmS 所管理的窗口并不是 Window 类,而是一个 View 或者 ViewGroup 类,一般就是指 DecorView 类,即一个 DecorView 就是 WmS 所管理的一个窗口。 Window 是一个 abstract 类型。

—
DecorView 类:该类是一个 FrameLayout 的子类,并且是 PhoneWindow 中的一个内部类。 Decor 的英文是 Decoration ,即“修饰”的意思, DecorView 就是对普通的 FrameLayout 进行了一定的修饰,比如添加一个通用的 Title bar ,并响应特定的按键消息等。

—
ViewRoot 类: WmS 管理客户端窗口时,需要通知客户端进行某种操作,这些都是通过异步消息完成的,实现的方式就是使用 Handler ViewRoot 就是继承于 Handler ,其作用主要是接收 WmS 的通知。

—
W 类:该类继承于 Binder ,并且是 ViewRoot 的一个内部类。

—
WindowManager 类:客户端要申请创建一个窗口,而具体创建窗口的任务是由 WmS 完成的, WindowManager 类就像是一个部门经理,谁有什么需求就告诉它,由它和 WmS 进行交互,客户端不能直接和 WmS 进行交互。

6.1.3
Linux驱动

Linux 驱动和 Framework 相关的主要包含两部分,分别是 SurfaceFlingger SF )和 Binder 。每一个窗口都对应一个 Surface SF 驱动的作用是把各个 Surface 显示在同一个屏幕上。

Binder 驱动的作用是提供跨进程的消息传递。

APK程序的运行过程

首先, ActivityThread main() 函数中开始执行,调用 prepareMainLooper() UI 线程创建一个消息队列 (MessageQueue)

然后创建一个 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

6.3
客户端中的线程

在多任务操作系统中,任何程序都运行在线程之中。系统首先会为客户端程序分配一个线程,然后该线程从程序的入口处开始执行。那么,请思考以下问题。

—
Android APK 程序中都有哪些线程?

—
什么是 UI 线程?

—
程序中自定义 Thread UI 线程的区别是什么?

首先,很明确地讲,包含有 Activity 的客户端程序至少包含三个线程,如图 6-1 所示。每个 Binder 对象都对应一个线程, Activity 启动后会创建一个 ViewRoot.W 对象,同时 ActivityThread 会创建一个 ApplicationThread 对象,这两个对象都继承于 Binder ,因此会启动两个线程,负责接收 Linux Binder 驱动发送 IPC 调用。最后一个主要线程也就是程序本身所在的线程,也叫做用户交互( UI )线程,因为所有的处理用户消息,以及绘制界面的工作都在该线程中完成。

为了验证这一点,可以在 Eclipse 中新建一个 Hello Android 的程序,然后以 debug 的方式运行,在 debug 窗口中会看到如图 6-1 所示的界面。

6-1
程序中线程

自定义 Thread UI 线程的区别在于, UI 线程是从 ActivityThread 运行的,在该类中的 main() 方法中,已经使用 Looper.prepareMainLooper() 为该线程添加了 Looper 对象,即已经为该线程创建了消息队列( MessageQueue ),因此,程序员才可以在 Activity 中定义 Handler 对象(因为声明 Handler 对象时,所在的线程必须已经创建了 MessageQueue )。而普通的自定义 Thread 是一个裸线程,因此,不能直接在 Thread 中定义 Handler 对象,从使用场景的角度讲,即不能直接给 Thread 对象发消息,但是却可以给 UI 线程发消息。

摘自:http://bbs.gfan.com/thread-2765273-1-1.html

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics