现在的位置: 首页 > 综合 > 正文

<>笔记 第6章 应用框架Framework概述

2013年08月28日 ⁄ 综合 ⁄ 共 3810字 ⁄ 字号 评论关闭

其实android就是基于Linux内核的一个GUI系统,只是他运行在手机上,各种资源都比较有限,而且他不仅处理按键事件,更主要的是处理触控事件;其整体架构可以参考下图(此图来源于网络):

本章主要是介绍其中的应用框架层(Application Framework),前面的章节已经提到android是基于多进程设计的,先看看如下手稿图(mac下没找到顺手的UML画图工具),其类名基于4.2.2版本:

从上图中可以看出,核心包括了3+X个进程:

  1. servicemanager守护进程:系统启动时自动启动,通过init.rc设置,主要用来加载binder驱动,实现SystemServer与APP进程之间的消息传递,进而实现IPC中转调用;
  2. surfaceflinger守护进程:系统启动时自动启动,通过init.rc设置,他也是一个驱动,每个窗口都对应一个Surface,该驱动的作用就是把各个Surface显示在同一个屏幕上;
  3. SystemServer进程:该进程是zygote孵化出的第一个进程(详见第9章的描述),可以理解为应用框架的服务端,用来提供各种系统服务,核心的包括窗口管理服务WindowManagerService、活动管理服务ActivityManagerService等;

    1. IActivityManager:管理所有应用程序中的Activity,其实现类是ActivityManagerService;当前台应用APP需要启动某个Activity时,需要先通过binder机制请求IActivityManager,OK之后再回调APP进程中的ActivityThread.ApplicationThread进行真正的Activity加载;
    2. IWindowManager:定义应用窗口各种操作的接口,其实现类是WindowManagerService,基于Binder框架实现各窗口的叠放次序、隐藏或显示;当系统接收到按键或触控事件之后驱动会中转到WindowManagerService,之后他回调APP进程中的PhoneWindow.W实现对各类消息的分发;
    3. IWindowSession:定义应用窗口和应用之间的会话,其实现类是Session;该会话是由IWindowManager负责open并维护的,他负责与APP直接打交道,通过binder机制实现IPC调用,APP通过它实现对IWindowManager的间接调用;
    4. 请大家思考一个问题:为什么APP不直接与IWindowManager打交道呢,还要通过IWindowSession来进行一次中转,这样不是反而让系统架构变得更复杂了吗?

      其实我也有这个疑问,目前我的理解是IWindowSession中加入了对输入法InputMethod的处理,他实现应用部分窗口和输入法窗口的整合;而IWindowManager是不关心是否有输入法的,在他眼中只有窗口,而窗口里面具有展示的是什么他是不关心的;
  4. APP所在进程:每个APP应用启动后都会是一个独立进程,这就是X的原因,有多少个应用,X就是多少;

    1. Context:Activity/Service组件的基类,可以理解为上下文或者场景,其实现类为ContextImpl;当我们调用startActivity()时就会通过binder机制远程调用到IActivityManager;
    2. Activity:android系统的4大基础组件之一,是应用程序的最小单元类,可以理解为一个页面的控制类,如同java服务端我们所说的action;
    3. IApplicationThread:应用进程提供给系统服务回调的binder接口,执行具体的Activity加载,其实现类为ActivityThread.ApplicationThread;
    4. ActivityThread:应用程序执行的主线程类,每个应用有且只有一个ActivityThread实例,入口为static main()函数,他所在的线程即为UI线程或主线程;
    5. Window:提供通用的窗口操作API的基类;注意:Wms中管理的窗口指的是View,并不是这个Window,这里的Window只是一个抽象类,android系统不仅仅可以在手机上运行,在其他设备上也可以运行,此时他们的窗口操作的实现可以完全不一样;
    6. PhoneWindow:继承至Window,即适用于手机上窗口操作的实现类;
    7. PhoneWindow.DecorView:继承于FrameLayout,他是应用窗口展示的顶级View容器(Top Level),即应用中自己加入的各种View控件其实都是DecorView的child;
    8. ViewParent:定义了View的父辈所需的各类操作API接口,其实现类是 ViewRootImpl/ViewGroup;
    9. ViewRootImpl:顶级容器DecorView的parent;

      当我们在APP中通过ActivityThread.handleResumeActivity加载具体的Activity中对应的页面内容时,会在WindowManager中将DecorView加入到窗口管理器,此时会将已经是顶级容器的DecorView的parent设置为 ViewRootImpl

      理解这一点至关重要,因为这直接影响到对事件机制的传递、View页面重绘等核心功能点的理解;
    10. IWindow:应用进程提供给系统服务回调的binder接口,用来接收Wms服务那边传入的按键、触控事件,并进行转换处理,其实现类为 ViewRootImpl.W;
    11. 在APP应用内部,为了确保用户体验的流畅性,系统大量使用了异步回调机制,确保UI主线程只负责与UI相关的事情,其余的事情全都异步处理;关于异步回调就涉及到系统对异步消息队列的设计,详见《第2章 Java基础》中的异步消息处理线程部分;

APK应用程序的运行过程

  1. 首先,应用的启动从ActivityThread中的static main()函数开始执行,调用prepareMainLooper()为UI主线程创建好消息队列MessageQueue;
  2. 创建ActivityThread实例,期间会创建好binder对象ApplicationThread、以及Handler实例H;其中前者负责接收远程Ams的IPC回调,收到消息后再通过H把消息发送到消息队列,然后UI主线程会从消息队列MQ中取出消息并执行响应的create、start、resume、pause、stop、destroy操作;
  3. 执行Looper.loop()让UI主线程进入消息循环,随时准备接收异步消息;
  4. 当ActivityThread接收到Ams发送的start某个Acitivity的请求之后,根据指定的intent信息创建指定的Activity对象;
  5. Activity在加载过程中会创建PhoneWindow实例,并将从layout中加载进来的View加入到DecorView容器中;
  6. 此后Activity需要将创建好的页面信息显示到屏幕上,于是调用IWindowManager在APP应用中的经纪人WindowManager,于是WindowManager创建一个 ViewRootImpl、以及W实例,并获得IWindowSession引用;
  7. WindowManager.addView() --> ViewRootImpl.setView() --> IWindowSession. addToDisplay() -->  IWindowManager.addWindow(); 之后再通过surfaceflinger将页面内容真正输出到屏幕;
  8. 当页面显示OK之后,用户在界面上进行各类按键、或触控操作,产生的各类消息都会经由InputDispatcherThread(4.2.2中已经由C++实现,之前老的版本由Java实现)转发到WindowManagerService中的Handler进行异步处理;而具体的处理过程就是判断消息属于哪个客户端的哪个窗口,然后通过binder机制回调到APP进程中IWindow的具体实例ViewRootImpl.W;
  9. 之后DecorView首先获得消息的处理权,如果DecorView不想处理该消息则会继续向子View传递,如果还没处理则传递给PhoneWindow(实际上就是调用了DecorView的相关dispatchXXX方法),最后才是传递给Activity(实现了Window.Callback接口);

    在View内部的消息传递机制详见后续的《第13章 View工作原理》;

自定义Thread与UI主线程的区别是什么?

UI主线程是从ActivityThread运行的,在main()方法中已经执行Looper.prepareMainLooper()为该线程添加了Looper对象,即已经为该线程创建了消息队列MessageQueue,因此大家可以在Activity中定义Handler对象;

而在普通的自定义Thread中却不能定义Handler对象,因为Handler对象在声明时要求所在线程必须已经创建了MessageQueue,不然没有队列怎么进行异步处理呢?

当然自定义裸Thread中可以通过手动添加消息队列之后也可以定义Handler;

抱歉!评论已关闭.