不管你是做手机系统开发还是APP开发,FrameWork层你肯定会碰到除非你所做的事情只是UI的优化,我来为大家讲解一下关于android framework中的设计模式?跟着小编一起来看一看吧!
android framework中的设计模式
不管你是做手机系统开发还是APP开发,FrameWork层你肯定会碰到。除非你所做的事情只是UI的优化。
那么Framework具体的工作是做什么呢? 简单一句话:提供Android开发人员一系列的服务和API的接口。
关于API接口如何查看:如何查看Android API文档以及Android5.0新增加的API接口:Android 5.0 新增和改进的API,感兴趣的同志可以看下。
Android Framework解析
Gooooood 关注
2016.05.07 21:21* 字数 2574 阅读 3868评论 4喜欢 18
众所周知,Android是一个基于Linux实现的操作系统。但对于Linux内核来说,Android也仅仅只是一个运行在内核之上的应用程序,与其他运行在内核之上的应用程序没有任何区别。所以Android也需要运行环境,需要Linux内核在启动完成后加载Android Framework运行所需要的资源。当Framework完成初始化后才能继续启动相应的APK应用程序。
Framework启动分析
Framework运行的第一个Java虚拟机进程为zygote(对应具体程序为app_process,该程序位于system/bin目录下),zygote是APK应用程序的父进程,此后所有的虚拟机进程都由zygote创建。
zygote有两个功能:
1.接受请求创建新的Dalvik进程
2.共享类和资源(需要加载的资源在preload-classes文本文件中声明)
Dalvik虚拟机进程间的关系
对于Android来说,每一个应用程序对应着一个Linux 进程,每一个进程都是一个Dalvik虚拟机,Dalvik虚拟机是一种类似Java虚拟机的实现。
zygote进程在启动时会预先装载共享类和共享资源,这些类及资源实际上就是SDK中定义的大部分类和资源。当zygote进程创建新进程时,新的APK进程只需装载自身类和资源即可。共享的资源位于同一段物理内存空间中,zygote进程及其创建的Dalvik进程都可以访问,这就解决了多个APK共享Framework资源的问题。(更多关于资源的讨论请看Android资源加载机制详解)
zygote创建的第一个进程名为SystemServer,SystemServer创建了一个Socket客户端,并创建了ActivityManagerService线程来管理该客户端。之后所有的Dalvik进程都是由该客户端启动的。当需要启动新的APK进程时,AmS会通过该Socket客户端向zygote进程的Socket服务端发送一个启动命令,然后zygote就会创建(使用fork()创建新进程)出新的应用程序进程。
系统服务
SystemServer进程内部运行着APK应用中能够直接交互的大部分系统服务。比如WindowManagerService(简称WMS),ActivityManagerService(简称AmS),PackageManagerService(简称PmS)等。这些系统服务都是以一个线程的方式生存在SystemServer进程中。SystemServer启动的各种服务线程如下所示:
PowerManagerService电源管理服务
ActivityManagerService管理Activity
PackageManagerService程序包管理服务
BatteryService电池管理服务
LightService自然光强度感应传感器服务
VibratorService震动传感器服务
ClipboardService剪切板服务
NetworkManagerService网络管理服务
InputMethodManagerService输入法管理服务
BluetoothService蓝牙服务
...
Dalvik与Android Runtime(ART)
Dalvik是一种类Java虚拟机的实现,其执行的是class优化后的dex字节码文件。Dalvik通过一个JIT(Just-In-Time)编译器去解释字节码,但执行效率并不理想。
自动Android 4.4后安卓就内置了ART实现,从5.0开始更是直接抛弃了Dalvik全面使用ART。ART通过AOT机制(Ahead-Of-Time)在应程序安装时将字节码编译成机器语言,因此执行速度更快。并且ART也完全兼容Dalvik。
应用程序启动分析
在计算机的世界里每个程序都有一个main()方法,程序代码都是从main()方法开始执行,Android应用程序也不例外。
当应用程序启动时系统首先会为其创建一个Dalvik虚拟机进程,并加载APK应用程序类及资源。然后,APK应用程序从ActivityThred的main()方法处开始执行。
首先main()方法为UI线程创建一个消息队列(MessageQueue)。然后创建ActivityThread对象,ActivityThread初始化时会创建一个Handler和一个Binder。Binder负责接收远程AmS的IPC调用,接收到调用后通过Handler将消息发送到消息队列,UI主线程会异步地从消息队列中取出消息并执行相应操作,比如start,stop,pause等。
接着UI主线程调用Looper.loop()方法进入消息循环体,进入后就会不断从消息队列中读取并处理消息。
ActivityThread是APK程序的UI线程,也就是我们所说的主线程。主线程要求执行时间不能超过5秒,超过就会报ANR,这个5秒就是UI线程消息队列循环一次的最大时间阈值。
当ActivityThread接收到AmS发送的start某个Activity消息后,就会创建指定Activity对象。Activity又会创建PhoneWindow类,PhoneWindow创建DecorView,DecorView内部包含Activity.setContentView(R.layout.xxx)指定的布局。
创建完成后,Activity需要将布局显示在屏幕上,于是调用WindowManager.addView()方法。WindowManager为Activity对应的窗口(Window)创建一个ViewRoot对象(每一个窗口对应一个ViewRoot对象),然后调用WmS提供的远程接口将窗口(布局)显示到屏幕上。至此应用程序中的Activity就显示在屏幕上了。
APK中的线程
在现在操作系统中,任何应用程序都运行在线程之中。客户端在启动时系统会首先为其分配一个线程,然后该线程从程序的入口处开始执行。对于包含Activity的客户端程序,至少包含三个线程:
主线程,又称UI线程,也就是应用程序本身所在的线程,主要用于处理用户消息以及绘制程序界面。
ViewRoot.W对象对应的线程,Activity启动后会创建一个ViewRoot.W对象,W对象继承自Binder,因此会启动一个对象负责接收Linux Binder驱动的IPC调用。
ApplicationThread对象所对应的线程,该对象也继承自Binder,因此也会启动一个线程用于IPC调用。
自定义Thread与UI线程的区别
对于UI线程,在启动时已经创建了消息队列(MessageQueue),既在ActivityThread的main()方法中已经使用Looper.prepareMainLooper()方法为UI线程添加了Looper对象。程序员可以直接在Activity中定义Handler对象发送处理消息。
而对于普通线程,需要手动调用Looper.prepareLooper()方法为Thread创建消息队列,这样才能定义Handler处理消息。即不能直接在Thread中定义Handler。
从使用场景上说,就是不能直接给Thread对象发消息,但是却可以给UI线程发消息。
具体Handler的使用及解释请移步Android异步通信机制详解
一些重要的类:
下面是一些系统中常见的类及其功能介绍,通读一遍会对理解Android源码很有帮助。
两个重要的系统服务
WindowManagerService,管理所有的窗口,包括创建删除窗口,隐藏显示窗口,决定窗口的层级顺序,指定当前正在与应用程序交互的窗口。
ActivityManagerService,内存管理,进程管理,统一调度所有应用程序中的Activity。所有Activity的启动必须通知AmS,AmS也决定了某个进程会不会被杀死。
两个消息处理类
KeyQ类:该类是WmS的内部类,继承自KeyInputQueue,一旦创建就立即启动一个线程,该线程会不断读取用户UI操作消息,比如按键、触摸屏、等,并把这些消息放到一个消息队列QueueEvent类中。
InputDispatcherThread类:该类一旦创建也会启动一个线程,该线程会不断地从QueueEvent中读取用户消息,并进行一定的过滤,过滤后发送给当前活动的而应用程序中。
其他常用类
ActivityThread类,应用程序主线程类,所有的APK都有且仅有一个ActivityThread类,程序的入口为该类中的static main()方法,ActivityThread所在的线程即为UI线程或主线程。
ViewRoot类,WmS管理客户端窗口时,需要通知客户端进行某种操作,这些都是通过IPC调用来完成的,而客户端在接收到IPC后,都需要将该调用转换成本地异步调用。ViewRoot继承自Handler,其作用就是将远程接口调用转换成本地异步调用。
W类,ViewRoot内部类,继承自Binder,Wms通知客户端时就是该类进行IPC调用。该类内部会向其所在的ViewRoot发送一个Handler消息,以便进行异步处理。
Window类,是一个抽象类,提供了一套操作窗口的通用方法(Callback接口)。Activity就是通过实现这个Callback接口来获得对消息的处理机会。因为消息首先会由WmS传递给窗口中的View树,View树不处理消息的话才会传递给Window,这时候就会回调Activity实现的Callback方法使Activity有机会处理事件。
PhoneWindow类,是Window的具体实现类,其内部保存有DecorView对象。
DecorView类,应用程序视图的根布局View,该类继承自FrameLayout。客户端使用WindowManager添加窗口就是将该类(及其子View)添加到WmS中,并将其所代表的视图绘制到屏幕上。
Activity类,该类APK程序最小运行单元。ActivityThread根据用户的操作选择加载哪个Activity。
WindowManager类,该类是WindowManagerService在客户端的管理类,客户端通过WindowManager申请创建一个窗口,而具体创建窗口的任务是由WMS来完成的。
现在许多厂商一般是做代码移植,然后可能会根据自己产品的特点在frameworks及整个平台里加自己的扩展功能。frameworks层多数是Java代码。下面是Frameworks的结构图:
Framework定义了客户端组件和服务端组件功能及接口。包含3个主要部分:服务端,客户端和Linux驱动。
一:服务端
服务端主要包含两个重要类,分别是WindowManagerService(Wms)和ActivityManagerService(Ams)。Wms的作用是为所有的应用程序分配窗口,并管理这些窗口。包括分配窗口大小,调节各窗口的叠放次序,隐藏或显示窗口。Ams的作用是管理所有应用程序中的Activity。
除此之外,在服务端还包括2个消息处理类:
1)KeyQ类:
该类为Wms的内部类,继承于KeyInputQueue类, KeyQ对象一旦创建,就立即启动一个线程,该线程会不断地读取用户的UI操作消息,比如按键、触摸屏、trackball、鼠标等,并把这些消息放到一个消息队列QueueEvent类中。
2)InputDispatcherThread类:
该类的对象一旦创建,也会立即启动一个线程,该线程会不断地从QueueEvent中取出用户消息,并进行一定的过滤(用Wms中相应函数处理),过滤后,再将这些消息发给当前活动的客户端程序中。
二:客户端
客户端主要包括以下重要类:
1)ActivityThread类:
该类为应用程序的主线程类,所有的Apk程序有且只有一个ActivityThread类,程序的入口为该类中的static main()函数。
2)Activity类:
该类为APK程序的一个最小运行单元,一个APK程序中可以包含多个Activity对象,ActivityThread主类会根据用户操作选择运行哪个Activity对象。
3)PhoneWindow类:
该类继承与Window类,同时,PhoneWindow类内部包含了一个DecorView对象。简而言之,PhoneWindow是把一个FrameLayout进行了一定的包装,并提供了一组通用的窗口操作接口。
4)Window类:
该类提供了一组通用的窗口(Window)操作API, 这里的窗口仅仅是程序层面上的,Wms所管理的窗口并不是Window类,而是一个View或者ViewGroup类,一般就是指DecorView类,即一个DecorView就是Wms所有管理的一个窗口。Window是一个abstract类型。
5)DecorView类:
该类是一个FrameLayout的子类,并且是PhoneWindow中的一个内部类。Decor的英文是Decoration, 即“修饰”的意思,DecorView就是对普通的FrameLayout进行了一定的修饰,比如添加一个通用的TitleBar, 并响应特定的按键消息等。
6)ViewRoot类:
Wms管理客户端窗口时,需要通知客户端进行某种操作,这些都是通过异步消息完成的,实现方式就是使用Handler, ViewRoot就是继承于Handler,其作用主要是接收Wms的通知。
7)W类:
该类继承于Binder, 并且是ViewRoot的一个内部类。
8)WindowManager类:
客户端要申请创建一个窗口,而具体创建窗口的任务是由Wms完成的,WindowManager类就像是一个部门经理,谁有什么需求就告诉它,由它和Wms进行交互,客户端不能直接和Wms进行交互。
三:Linux驱动
Linux驱动和Framework相关的主要包含两部分,分别是SurfaceFlingger(SF)和Binder。每一个窗口都对应一个Surface, SF驱动的作用是把各个Surface显示在同一屏幕上。Binder驱动的作用是提供跨进程(IPC)的消息传递机制。
一、FrameWork整体运行框架说明:
1.Activity的创建会创建PhoneWindow,PhoneWindow会创建DocerView,DocerView会创建View和ViewGroup。
2.应用程序在Activity中添加和删除窗口,是通过调用WindowManager类的addView和RemoveView函数达成,具体实现是通过桥接模式实现的WindowManagerImpl来实现。进而转向调用ViewRoot类的setView和removeViewLocked,然后通过IPC机制调用到WMS中的addWindow和removeWindow来完成。
3.当AMS通知ActivityThread销毁某个Activity时,ActivityThread会直接调用WindowManager的removeView方法删除窗口,实现在WindowManagerImpl类。
4.AMS调用WMS,一般情况是告诉WMS一些消息,比如某个新的Activity要启动了,从而WMS会保存一个该Activity记录的引用,有时也会直接调用WMS的接口,比如切换窗口时,启动切换窗口是直接调用WMS的setAppStartingWindow。
5.WMS内部是全权接管了输入消息的处理和屏幕的绘制,输入消息的处理是借助于InputManager类完成,InputManger类会生成两个线程InuptReaderThread和InputDispatcherThread,InuptReaderThread循环地从EventHub读取输入消息,对于非大数据是通过channel方式(InputChannel会生成serverChannel和ClientChannel)派发消息,对应大数据则是通过共享缓存ShareMemory分发消息;InputDispatcherThread会从Channel或者ShareMemory获取消息并派发,派发是通过InputPublisher,应用层客户端通过InputConsumer不断从Channel或者ShareMemory获取派发的消息,进而交由ViewRoot处理。其中InputPublisher,InputPublisher和InputConsumer是由InputMoniter生成。
所以InuptReaderThread和EventHub是生产者,InputDispatcherThread是消费者,InputMoniter是消费渠道,ViewRoot是消费者和生产者的桥梁,WMS和AMS是家庭夫妻双管家。
二、FrameWork启动流程
Android启动过程包含从Linux内核加载到Home应用程序启动的整个过程。整体流程如下:
Android是基于Linux内核的系统平台。启动时,首先通过bootloader(系统加载器),加载Linux内核。在Linux加载启动时,与普通的Linux启动过程相同,先初始化内核,然后调用Init进程。
Init进程启动zygote:解析配置文件:init.rc(系统配置文件)及initXXX.rc(与硬件平台相关的文件)的内容执行一系列的命令,包括创建Mount目录,安装文件系统,设置属性,启动属性服务器,启动Socket服务端口-》加载preload-classes和preload-resources(Framework大部分类及资源)-》fork启动新的进程Zygote(其实是由fork和execv共同创建)。
Zygnote孵化第一个进程SystemServer,SystemServer启动各种系统服务线程。SystemServer进程在Android的运行环境中扮演了"神经中枢"的作用,APK应用中能够直接交互的大部分系统服务都在该进程中运行,常见的比如WindowManagerServer(Wms)、ActivityManagerSystemService(AmS)、PackageManagerServer(PmS)等,这些系统服务都是以一个线程的方式存在于SystemServer进程中。SystemServer的main()函数首先调用的是init1()函数,这是一个native函数,内部会进行一些与Dalvik虚拟机相关的初始化工作。该函数执行完毕后,其内部会调用Java端的init2()函数,该函数首先创建了一个ServerThread对象,该对象是一个线程,然后直接运行该线程,于是,从ServerThread的run()方法内部开始真正启动各种服务线程。
基本上每个服务都有对应的Java类,从编码规范的角度来看,启动这些服务的模式可归类为三种:模式一是指直接使用构造函数构造一个服务,由于大多数服务都对应一个线程,因此,在构造函数内部就会创建一个线程并自动运行。模式二是指服务类会提供一个getInstance()方法,通过该方法获取该服务对象,这样的好处是保证系统中仅包含一个该服务对象。模式三是指从服务类的main()函数中开始执行。无论以上何种模式,当创建了服务对象后,有时可能还需要调用该服务类的init()或者systemReady()函数以完成该对象的启动
当以上服务线程都启动后,AMS以systemReady调用完成最后启动,mMainStack.resumeTopActivityLocked(null)-》mService.startHomeActivityLocked启动第一个Activity。至此,FrameWorkd启动完成。
SystemServer中启动服务列表
服务类名称
作用描述
启动模式
EntropyService
提供伪随机数
1.0
PowerManagerService
电源管理服务
1.2/3
ActivityManagerService
最核心的服务之一,管理Activity
自定义
TelephonyRegistry
通过该服务注册电话模块的事件响应,比如重启、关闭、启动等
1.0
PackageManagerService
程序包管理服务
3.3
AccountManagerService
账户管理服务,是指联系人账户,而不是Linux系统的账户
1.0
ContentService
ContentProvider服务,提供跨进程数据交换
3.0
BatteryService
电池管理服务
1.0
LightsService
自然光强度感应传感器服务
1.0
VibratorService
震动器服务
1.0
AlarmManagerService
定时器管理服务,提供定时提醒服务
1.0
WindowManagerService
Framework最核心的服务之一,负责窗口管理
3.3
BluetoothService
蓝牙服务
1.0
DevicePolicyManagerService
提供一些系统级别的设置及属性
1.3
StatusBarManagerService
状态栏管理服务
1.3
ClipboardService
系统剪切板服务
1.0
InputMethodManagerService
输入法管理服务
1.0
NetStatService
网络状态服务
1.0
NetworkManagementService
网络管理服务
NMS.create()
ConnectivityService
网络连接管理服务
2.3
ThrottleService
暂不清楚其作用
1.3
AccessibilityManagerService
辅助管理程序截获所有的用户输入,并根据这
些输入给用户一些额外的反馈,起到辅助的效果
1.0
MountService
挂载服务,可通过该服务调用Linux层面的mount程序
1.0
NotificationManagerService
通知栏管理服务,Android中的通知栏和状
态栏在一起,只是界面上前者在左边,后者在右边
1.3
DeviceStorageMonitorService
磁盘空间状态检测服务
1.0
LocationManagerService
地理位置服务
1.3
SearchManagerService
搜索管理服务
1.0
DropBoxManagerService
通过该服务访问Linux层面的Dropbox程序
1.0
WallpaperManagerService
墙纸管理服务,墙纸不等同于桌面背景,
在View系统内部,墙纸可以作为任何窗口的背景
1.3
AudioService
音频管理服务
1.0
BackupManagerService
系统备份服务
1.0
AppWidgetService
Widget服务
1.3
RecognitionManagerService
身份识别服务
1.3
DiskStatsService
磁盘统计服务
1.0
,