Android控件系统(二)——Framework概述

Framework框架

  Framework定义了客户端组件和服务器端组件功能及接口,包含3个部分:服务端、客户端和linux驱动,以下图所示: linux

image

  Framework中所包含的服务是很是多的,为了清晰的描述服务端、客户端和linux驱动三者的关系,咱们只是描述了它们其中的一小部分,这一小部分也是为后续讲解窗口的建立、Activity启动、绘制、事件分发服务的。程序员

服务端

  服务端主要包含两个重要类,分别是WindowManagerService(WMS)和ActivityManagerService(AMS):api

  • WMS:做用是为全部的应用程序分配窗口,并管理这些窗口。包括分配窗口的大小、叠放个窗口的叠放次序、隐藏或显示窗口;
  • AMS:做用是管理全部应用程序中的Activity;

  除此以外,在服务端还包括2个信息处理类:服务器

  • KeyQ:该类为wms的内部类,继承于keyinputQueue类,keyQ对象一旦建立,就当即启动一个线程,该线程会不断地读取用户的ui操做消息,好比按键、触摸屏、trackball、鼠标等。并把这些消息放到一个消息队列QueueEvent类中;
  • InputDispatcherThread:该类的对象一旦建立,也就当即启动一个线程,该线程会不断地从QueueEvent中取出用户消息,并进行必定的过滤,用wms中的相应函数来作过滤处理,过滤后,再将这些消息发给当前活动的客户端程序中。

客户端

客户端主要包括如下重要类:框架

  • 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驱动

  Linux驱动和Framework相关的主要包含两个部分,分别是surfaceFlingger和Binder,每个窗口都对应一个Surface,sf驱动的做用就是把各个surface显示在同一个屏幕上。
  Binder驱动的做用是提供框进程 ipc 的消息传递机制。

APK程序的运行过程

下图是一个更加完成的APK程序工做的流图:

image
  首先,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。

客户端中的线程

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

  • Android APK程序中都有哪些线程?
  • 什么是UI线程?
  • 程序中自定义Thread和UI线程的区别是什么?

  首先,很明确地讲,包含有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线程发消息。

相关文章
相关标签/搜索