任何控制类程序都有一个入口,语言的入口是由处理器内部的复位(Reset)中断向量表决定的;C程序入口是main()函数;JAVA程序的入口必须是某个类的静态成员方法main()
Android程序也不例外,那么Android程序入口在哪里呢?Android FrameWork都包含哪些系统服务?这些系统服务是如何与AndroidAPK程序配合的?看完这个博客你就会对FrameWork有一定的了解了,如果觉得我的博客写的好的话,记得在博客下方写个好的评论,欢迎转载,请标明出处
FrameWork定义了客户端组件和服务端组件功能及接口。
框架中包含三个主要部分,分别服务端,客户端,和Linux驱动
一,服务端
服务端主要包含两个重要的类,分别是WindowManagerService(Wms)和ActivityManagerService各窗口的叠放次序,隐藏或者显示窗口,Ams的作用是管理所有的应用程序的Activity,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)线程,因为所有的处理用户消息,以及绘制界面的工作都在该线程中完成。
在上边的图片中我们看到了这么几个方Native状态的线程:分别是main,Binder1,Binder2,从这个图片中我们就可以看出自定义的Thread和UI线程的区别在于,UI线程是从ActivityThread运行的,在该类汇总的main()方法中,已经使用LoopareMainLooper()为该线程添加了Looper对象,即已经为该线程创建了消息队列(MessageQueue),因此,程序员才可以在Activity中定义Handler对象(因为声明Handler对象时,所在的线程必须创建MessageQueue).而普通的自定义Thread是一个裸线程,因此不能直接在Thread中定义Handler对象,从而使用场景来讲,即不能直接给Thread对象发消息,但可以给UI线程发消息
首先,提出这个问题是因为,我们需要不同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都很容易获得引用.