### 我眼中的Android Framework
在开发中我们会遇到各种各样的非常奇怪的问题,有些问题是百思不得骑姐。其实这些问题大都是因为我们不了解安卓内部运行原理,知其所以然才是我们的目的。—前言
任何控制类程序都有一个入口,安卓程序也是。
framework包含三个部分:服务端、客户端、linux驱动。
### 服务端
服务端主要包含两个重要的类:WindowManagerService和ActivityManagerService
### 客户端
包含以下类:
-
ActivityThread:是应用程序的主线程类,它所在的线程就是UI线程或者主线程。
-
Activity:ActivityThread会根据用户操作选择加载哪个Activity对象。
-
PhoneWindow:继承于Window类,内部包含一个DecorView对象,并提供了一些通用窗口操作API。
-
Window:一个抽象类,提供了一些通用的窗口操作API。注意:WindowManagerService管理的窗口不是Window类,其实是View和ViewGroup。
-
DecorView:FrameLayout的子类,DecorView是对FrameLayout进行了一些修饰,从名字就可以看出来。
-
ViewRoot:继承于Handler,主要作用是把WindowManagerService的IPC调用转换为本地的一个异步调用。
-
W类:继承于binder,是ViewRoot内部类。主要帮助ViewRoot实现把WindowManagerService的IPC调用转换为本地的一个异步调用。
-
WindowManager:客户端如果想创建一个窗口先告诉WindowManager,然后它再和WindowManagerService交互,客户端不能直接和Wms交互。
### Linux驱动
Linux启动和Framework相关的主要是两个部分:SurfaceFlingger和Binder。
每一个窗口都对应一个Surface,SF主要是把各个Surface显示到同一屏幕上。Binder是提供跨进程的消息传递。
### 下面借助apk程序的运行过程去理解上面各个组件在何时起到何作用
ActivityThread从main()函数中执行,然后调用prepareMainLooper()为UI线程创建一个消息队列即MessageQueue。
然后创建ActivityThread对象,创建过程会创建一个Handler对象和一个Binder对象,其中Binder负责接收远程Ams的IPC调用,接收到调用后通过Handler把消息发送到消息队列,UI线程则会异步的从消息队列中取出消息并执行相应操作,比如 start、stop、pause。
然后UI线程调用Looper.loop()方法进入消息循环体,进入后就会不断地从消息队列中读取并处理消息。
当ActivityThread接收到Ams发送start某个Activity后就会创建指定的Activity对象。Activity会创建PhoneWindow->DecorView->创建相应的View或ViewGroup。创建完成后调用WindowManager把界面显示到屏幕上,然后创建ViewRoot,然后调用Wms提供的远程接口添加一个窗口并显示到屏幕上。
接下来就是用户的操作,事件线程不断的把消息放到事件队列中去,然后事件分发线程逐个取出消息,然后调用Wms中的相应函数处理该消息。
### 上面的过程会涉及到很多线程,顺便讲一下关于线程的几个疑惑
1.安卓程序中都有哪些线程?
客户端程序至少包含三个线程,Activity启动后会创建一个ViewRoot.W对象,同时ActivityThread会创建一个ApplicationThread对象,这两个对象继承Binder,每个Binder对应一个线程,因此会启动两个,负责接收Linux Binder驱动发送的IPC调用。还有一个当然是UI线程。
2.UI线程是什么?
用户交互线程,因为所有的处理用户消息,以及绘制页面的工作都在该线程中完成。
3.自定义的线程和UI线程有什么区别?
UI线程是从ActivityThread运行的,在该类的main()方法中已经使用了Looper.prepareMainLooper()为该线程添加了Looper对象,即已经为该线程创建了消息队列,因此,我们才可以在Activity中去定义Handler对象,因为创建Handler对象时其线程必须已经创建了消息队列。而普通的Thread则没有默认创建消息队列,所以不能直接在Thread中直接定义Handler,这个就是我们不懂程序运行原理导致的困惑。
转载注明出处,如有问题请留言。