Android内核之FrameWork学习

前言

任何控制类程序都有一个入口,语言的入口是由处理器内部的复位(Reset)中断向量表决定的;C程序入口是main()函数;JAVA程序的入口必须是某个类的静态成员方法main()
Android程序也不例外,那么Android程序入口在哪里呢?Android FrameWork都包含哪些系统服务?这些系统服务是如何与AndroidAPK程序配合的?看完这个博客你就会对FrameWork有一定的了解了,如果觉得我的博客写的好的话,记得在博客下方写个好的评论,欢迎转载,请标明出处

FrameWork框架

FrameWork定义了客户端组件和服务端组件功能及接口。
框架中包含三个主要部分,分别服务端,客户端,和Linux驱动
一,服务端
服务端主要包含两个重要的类,分别是WindowManagerService(Wms)和ActivityManagerService各窗口的叠放次序,隐藏或者显示窗口,Ams的作用是管理所有的应用程序的Activity,Wms主要负责窗口的控制,除此之外,在服务端还包括两个消息处理类,这两个类分别为:

  • KeyQ类:该类为WmS的内部类,继承于KeyInputQueue类,KeyQ对象一旦创建,就立即开动一个线程,该线程会不断的读取用户的UI操作信息,比如按键,触摸屏,trackball,鼠标等等;
  • InputDispatcherThread类:该类的对象一旦创建,也会立即启动一个线程,该线程会不断地从QueueEvent中取出用户消息,并进行一定的过滤,过滤后,在将这些消息发送给当前活动的客户端程序中.
    二,客户端
    客户端主要包括以下重要类:
  • ActivityThread类:该类为应用程序的主线程类,所有的APK程序都有且一个ActivityThread类,程序的入口为该类中的static main()函数,ActivityThread所在的线程即为UI线程或者为主线程
  • Activity类:该类为APK的一个最小运行单元.换句话说就是主线程动态加载可执行代码的最小单元类,一个APK程序中可以包含多个Activity对象,ActivityThread主类会根据用户操作选择动态加载哪个Activity对象
  • PhomeWindow类:该类继承于Window类,同时,PhoneWindow类内部包含一个DecorView对象,DecorView的父类是FrameLayout,因此PhoneWindow是内涵一个View对象,并提供了一组通过窗口的API;
  • Window类:该类提供了一组通用的窗口(Window)操作API.这里的窗口仅仅是客户端程序层面上的,Wms所管理的窗口并不是Window类,而是一个View或者是一个ViewGroup类,对于PhoneWindow类而言就是其内部包含的DecorView类.Window是一个abstract类型. 是一个抽象类
  • DecorView类:该类是一个FrameLayout的子类,并且是PhoneWindow种的一个内部类,DecorView的英文是Decoration,即”修饰”的意思,DecorView就是对普通的FrameLayout进行了一定的修饰,比如添加一个通用的Title bar,并响应特定的按钮信息等;
  • 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(SF)和Binder,每个窗口对应一个Surface,SF驱动的重用是把各个Surface显示在同一个屏幕上.
Binder驱动的作用是提供跨进程的消息传递,消息传递过程可以参照我的Android内核之Binder

APK程序的执行过程
首先,ActivityThrad从main()函数中开始执行,调用prepareMainLooper()为UI线程创建一个消息队里(MessageQueue).
然后创建一个ActivityThread对象,在ActivityThread的初始化代码中H(Handler)对象和一个Application对象(Binder)对象,其中Binder对象负责接收远程AmSterdam的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类,创建了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系统都有哪些线程?什么是UI线程?程序自定义Thread和UI线程有区别是什么?
首先,很明确地讲,包含有Activity的客户端至少包含三个线程。每个Binder对象都对应一个线程,Activity启动后创建一个ViewRoot,W 对象,同时ActivityThread会创建一个ApplicationThread对象,这两个对象继承于Binder,因此会启动两个线程,负责接收Linux Binder驱动发送IPC调用,最后一个主要的线程也就是程序本身所在的线程,也叫用户交互(UI)线程,因为所有的处理用户消息,以及绘制界面的工作都在该线程中完成。Android程序中的线程
在上边的图片中我们看到了这么几个方Native状态的线程:分别是main,Binder1,Binder2,从这个图片中我们就可以看出自定义的Thread和UI线程的区别在于,UI线程是从ActivityThread运行的,在该类汇总的main()方法中,已经使用LoopareMainLooper()为该线程添加了Looper对象,即已经为该线程创建了消息队列(MessageQueue),因此,程序员才可以在Activity中定义Handler对象(因为声明Handler对象时,所在的线程必须创建MessageQueue).而普通的自定义Thread是一个裸线程,因此不能直接在Thread中定义Handler对象,从而使用场景来讲,即不能直接给Thread对象发消息,但可以给UI线程发消息

Activity之间是如何传递消息(数据)

首先,提出这个问题是因为,我们需要不同Activity之间传递数据,然而这个问题本身就有问题,所谓”传递消息”一般是指多个线程之间的,而Activity本身并不是线程,ActivityThread才是一个JAVA类而已,就像Rectangle,Trigle类一样,如果有人问你他两要怎么传递消息你会不会觉得很奇怪?
事实上,如果要在两个类中传递数据,方法有很多 .
方法一:可以现实实例化某个类,获得该类的引用,当其他类需要该对象内部数据时,可以直接通过引用去访问该类的内部数据.
方法二:对于A,B两个类之间,可以先实例化一个第三方类C,然后两个类都可以把需要传递的数据存入C中,或者从C中取出.
这些方法理论上都可以在Activity类之间传递数据,然而,与普通类传递数据有所不同,普通类的实例化都是成员显示完成的,而Activity类的实例化却是由FrameWork完成的,程序员只能使用startActivity()方法来告诉FrameWork去运行哪个Activity,这就意味着程序员不能得到Activity对象的引用,那么久不能直接访问额你不数据,解决这个问题的方法就是Activity.getApplication()函数,该函数能够返回一个Application对象,该Application对象在该程序中是唯一的,同一个程序中不同的Activity调用该函数返回的Application对象是相同的,该对象的名称可以在AndroidManifest.xml中指定,一旦获取了该Application对象,就可以借组该对象,在不同的Activity之间传递数据.
除此之外,FrameWork本身也提供了标准的Activity之间传递数据的方法,即Intent类,该类作为startActivity()参数,仅用于启动Activity时传递给目标Activity,同时,如果调用startActivityResult(),目标Activity结束后,也会返回一个Intent对象给原Activity.
另外,从设计理念的角度来看,Android认为,两个Activity如果要共享数据,可以通过PerferenceStorage或者文件,数据库进行,同时一般情况下,设备上只会有一个Activity在允许,因此,多个Activity之间传递数据也不是必须的,如果某个Activity需要在停止后还能处理数据,那么该Activity似乎更应该设计一个后台Thread或者一个Service都很容易获得引用.

窗口相关类的概念

  • 窗口(非Window类):这是一个春雨发的说法,即程序员看到的屏幕上某个独立的界面,比如一个带有Title Bar的Activity界面,一个对话框,一个Menu菜单等,这些都能称为窗口, 在Android的引文相关文档使用的是Window这个单词,而从Wms的角度来讲,窗口是接收用户消息的最小单元,Wms内部用特定的类表示一个窗口,而给Wms中添加一个窗口是调用WindowManager类的addView()方法,也就是说,从WmS的角度来看,所谓添加一个窗口实际上是添加一个View对象,以至于这个View对象是来自于Activity还是用户自定义的一个View都不是很重要,Wms接收用户消息后,首先要判断这个消息属于哪个窗口,即哪个View对象,然后同IPC调用这个消息传递给客户端的ViewRoot子类.
  • Window类:该类在android.view包中, 是一个abstract类,该类抽象了”客户端窗口”的基本操作,并且定义了一组Callback接口,Activity类就是通过实现这个Callback接口以获得对象消息处理的机会的,因为消息最初是由WmS传递给View对象的
  • ViewRoot类:该类在android.view包中,客户端申请创建窗口时需要一个客户端代理,用以和WmS进行交互,ViewRoot内部类W就是完成p这个功能的,Wms所管理的每一个窗口都会对应一个ViewRoot类.
  • W类:该类是ViewRoot的一个内部类,继承与Binder,用于向WmS提供一个IPC接口,从而让WmS控制窗口客户端的行为
    描述一个窗口之所以使用这么多类的原因在于,窗口的概念存在于客户端和服务端(Wms)之中,并且FrameWork又定义了一个Window类,这让人容易产生混淆,实际上WmS所管理的窗口和Window类没有任何关系.
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值