Framework框架

  摘自:柯元旦 《Android内核剖析》
   任何控制类程序都有一个入口,汇编程序的入口由处理器内部的复位(Reset)中断向量表决定;C程序的入口是main()函数,一个C程序只能有一个main()函数;Java程序的入口必须是某个类的静态成员函数main().
  对于依赖于操作系统的程序,客户程序除了包含一个程序入口外,还需要和相关系统服务一起运行,以完成指定的任务。Android程序也不例外,那么,Android程序的入口在哪里?Android Framework都包含哪些必需的系统服务?这些系统服务是如何与Android apk程序配合的?本章将回答这些问题。
Framework框架
  Framework定义了客户端组件和服务端组件功能及接口。以下阐述中,“应用程序一般是指.apk”程序。
  框架中包含三个主要部分,分别为服务端、客户端和Linux驱动。
1.服务端
  服务端主要包含两个重要类,分别是WindowManagerService(WmS)和ActivityManagerService(AmS).WmS管理各窗口的叠放次序,隐藏或者显示窗口。AmS的作用是管理所有应用程序中的Activity.
  除此之外,在服务端还包括两个消息处理类:
1> KeyQ类:该类为WmS的内部类,继承于KeyInputQueue类,KeyQ对象一旦创建,就立即启动一个线程,该线程会不断地读取用户的UI操作消息,比如按键、触摸屏、trackball、鼠标等,并把这些消息放到一个消息队列QueueEvent类中。
2> InputDispatherThread类:该类的对象一旦创建,也会立即启动一个线程,该线程会不断地从QueueEvent中取出用户消息,并进行一定的过滤,过滤后,再将这些消息发送给当前活动的客户端程序中。

2. 客户端
客户端主要包括以下重要类:
1> ActivityThread类:该类为应用程序的主线程类,所有的APK程序都有且仅有一个ActivityThread类,程序的入口为该类中的static main()函数,ActivityThread所在的线程即为UI线程或主线程。
2> Activity类:该类为APK程序的一处最小运行单元,换句话说就是主线程动态加载可执行代码的最小单元类,一个apk程序中可以包含多个Activity对象,ActivityThread主类会根据用户操作先把动态加载哪个Activity对象。
3> PhoneWindow类:该类继承于Window类,同时,PhoneWindow类内部包含了一个DecorView对象,DecorView的父类是FrameLayout,因此,PhoneWindow是内含一个View对象,并提供了一组通用窗口操作API.
4> Window类:该类提供了一组通用的窗口操作API,这里的窗口仅仅是客户端程序层面上的,WmS所管理的窗口并不是Window类,而是一个View或者ViewGroup类,对于PhoneWindow类而言就是其内部包含的DecorView类。Window是一个abstract类型。
5> DecorView类:该类是一个FrameLayout的子类,并且是PhoneWindow中的一个内部类。Decor是”修饰“的意思,DecorView就是对普通的FrameLayout进行了一定的修饰,比如添加一个通用的Titlebar,并响应特定的按键消息等。
6> ViewRoot类:WmS管理客户端窗口时,需要通知客户端进行某种操作,这些都是通过IPC调用完成的,而在客户端窗口收到IPC调用后,都会把该调用转换为本地的一个异步调用,实现的方式就是使用Handler,ViewRoot就是继承于Handler,其作用主要是把WmS的IPC调用转换为本地的一个异步调用。
7> W类:该类继承于Binder,并且是ViewRoot的一个内部类。WmS通知客户端窗口时,是通过IPC调用,也就是调用到该Binder类,然后该Binder内部的处理函数一般会给该类所在的ViewRoot类发送一个Handler消息,以便进行异步处理。
8> WindowManager类:客户端要申请创建一个窗口,而具体创建窗口的任务是由WmS完成的,WindowManager类就像是一个部门经理,谁有什么需要就告诉它,由它和WmS进行交互,客户端不能直接和WmS进行交互。

3. Linux驱动
  Linux驱动和Framework相关的主要包含两个部分,分别是SurfaceFlingger(SF)和Binder。每一个窗口都对应一个Surface,SF驱动的作用是把各个Surface显示在同一个屏幕上。Binder驱动的作用是提供跨进程的消息传递。
APK 程序的运行过程
   首先,ActivityThread从mian()函数中开始执行,调用prepareMainLooper()为UI线程创建一个消息队列(MessageQueue).
   然后创建一个ActivityThread对象,在ActivityThread的初始化代码中会创建一个H(Handler)对象和一个ApplicationThread(Binder)对象。其中Binder负责接收远程AmS的IPC调用,接收到调用后,则通过Handler把消息发送到消息队列,UI主线程会异步地从消息队列中取出消息并执行相应的操作。
   接着,UI主线程调用Looper.loop()方法进入消息循环体,进入后就会不断地从消息队列中读取关处理消息。
   当ActivityThread接收到AmS发送start某个Activity后,就会创建指定的Activity对象。Activity又会创建PhoneWindow类-->DecorView类-->创建相应的ViewGroup.创建完成后,Activity需要把创建好的界面显示到屏幕上,于是调用WindowManager类,后才于是创建一个ViewRoot对象,该对象实际上创建了ViewRoot类和W类,创建ViewRoot对象后,WindowMangager再调用WmS提供的远程接口完成添加一个窗口并显示到屏幕上。
   接下来,用户开始在程序界面上操作。KeyQ线程不断把用户消息存储到QueueEvent队列中,InputDispatcherThread线程逐个取出消息,然后调用WmS中的相应函数处理该消息。当WmS发现该消息属于客户端某个窗口时,就会调用相应窗口的W接口。
   W类是一个Binder,负责接收WmS的IPC调用,并把调用消息传递给ViewRoot,ViewRoot再把消息传递给UI主线程ActivityThread,ActivityThread解析该消息并做相应的处理。在客户端程序中,首先处理消息的是DecorView,如果DecorView不想处理某个消息,则可以将该消息传递给其内部包含诉子View或者ViewGroup,如果还没有处理,则传递给PhoneWindow,最后再传递给Activity.
客户端中的线程
  在多任务操作系统中,任何程序都运行在线程之中。系统首先会为客户端程序分配一个线程,然后该线程从程序的入口处开始执行。那么,思考以下几个问题:
1> Android APK程序中都有哪些线程?
2> 什么是UI线程?
3> 程序中自定义的Thread和UI线程的区别是什么?

  首先,很明确地讲,包含有Activity的客户端程序至少包含三个线程,如图所示:

    

    每个Binder对象都对应一个线程,Activity启动后会创建一个ViewRoot.W对象,同时ActivityThread会创建一个ApplicationThread对象,这两个对象都继承自Binder,因此会启动两个线程,负责接收Linux Binder驱动发送IPC调用。最后一个产要线程也就是程序本身所在的线程,也叫做用户交互(UI)线程,因为所有的处理用户消息,以及绘制界面的工作都在该线程中完成。
  自定义的Thread和UI线程的区别在于,UI线程是从ActivityThread运行的,该类的main()方法中,已经使用Looper.prepareMainLooper()为该线程添加了Looper对象,即已经为该线程创建了消息队列,因此,程序员才可以在Activity中定义Handler对象(因为声明Handler对象时,所在的线程必须已经创建了MessageQueue)。而普通的自定义Thread是一个裸线程,困此,不能直接在Thread中定义Handler对象,即不能直接给Thread对象发送消息,但是却可以给UI线程发消息。


   下面讨论几个常见问题:
1. Activity之间如何传递消息
  程序员需要在不同的Activity之间传递数据,然后,这个问题本身就有问题。所谓“传递消息”一般是指多个线程之间,而Activity本身并不是线程,ActivityThread才是,Activity只是一个Java类而以,就像Rect、Trigle类一样,如果有人问"Rect类和Trigle类之间如何传递消息",是不是有点奇怪。
  事实上,如果要在两个类中传递数据,方法可以有很多。
  方法1:可以先实例化某个类,获得该类的引用,当其他类需要该对象的内部数据时,可以直接通过该引用去访问该类的内部数据。
  方法2:对于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,同时,如果调用startActivityForResult(),目标Activity在结束后,也会返回一个Intent对象给原Activity.
    Android认为,两个Activity如果要共享数据,可以通过preference storage或者文件、数据库进行,同时,在一般情况下,设备上只会有一个Activity在运行,因此,多个Activity之间传递数据也不是必需的。如果某个Activity需要在停止后还能处理某些数据,那么,该Acitivity似乎更应该被设计为一个后台的Thread或者是一个Service,无论是Thread还是Service都很容易获得其引用。
2. 窗口相关的概念
   经常会碰到以下几个概念,窗口、Window类、ViewRoot类以及W类,本节介绍这些概念的联系和区别。
1> 窗口(非Window类):即程序员所看到的屏幕上的某个独立的界面,比如一个带有Title Bar的Activity界面、一个对话框、一个Menu菜单等,这些都称之为窗口。本书中所说的窗口管理一般也都泛指所有这些窗口,在Android的英文相关文章中则直接使用Window这个单词。而从WmS的角度来讲,窗口是接收用户消息的最小单元,WmS内部用特定的类表示一个窗口,而给WmS中添加一个窗口是调用 WindowManager类的addView()方法,也就是说,从WmS的角度来看,所谓添加一个窗口实际上就是添加一个View对象,至于这个View对象是来看于Activity还是用户自定义的View都不重要,WmS接收到用户消息后,首先要判断这个消息属于哪个窗口,即哪个View对象,然后通过IPC调用把这个消息传递给客户端的ViewRoot.W子类。
2> Window类:该类在android.view包中,是一个abstract类,该类抽象了“客户端窗口”的基本操作,并且定义 了一组Callback接口,Activity类就是通过实现这个Callback接口以获得对消息处理的机会的,因为消息最初是由WmS传递给View对象的。
3> ViewRoot类:该类在android.view包中,客户端申请创建窗口时需要一个客户端代理,用以和WmS进行交互,ViewRoot内部类W就是完成这个功能的。WmS所管理的每一个窗口都会对应一个ViewRoot类。
4> W类:该类是ViewRoot类的一个内部类,继承于Binder,用于向WmS提供一个IPC接口,从而让WmS控制窗口客户端的行为。
   描述一个窗口之所以使用这么多类的原因在于,窗口的概念存在于客户端和服务端(WmS)之中,并且Framework又定义了一个Window类,这很容易让人混淆,实际上WmS所管理的窗口和Window类没有任何关系。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 框架Framework)是指一种可以用来构建软件系统的基础结构,它可以包含一系列的类、库、API等组件,提供了一些通用的功能和接口,以便开发人员可以更加高效地进行软件开发。框架可以在不同的应用程序中重复使用,以帮助开发人员减少开发时间、提高开发效率和代码的可重用性。常见的框架有Web框架、前端框架、游戏引擎等等。 ### 回答2: 框架framework)是指一种软件或系统的结构,为实现特定功能或解决问题而提供了一系列的工具、函数、类和接口。它可以看作是一种模板或蓝图,为开发人员提供了一种更高效、一致性和可维护性的开发方式。 框架通常包含了一些已经完成的通用功能,如用户认证、数据管理、界面设计等,开发人员只需根据自己的需求在框架的基础上进行定制化开发,避免了从零开始编写重复性代码的繁琐过程。通过规范化的架构和设计模式,框架能够提高代码的可读性和可扩展性,降低了系统的开发和维护成本。 框架有助于团队协作,提供了标准的开发流程和代码风格。同时,框架的生态系统也非常丰富,拥有大量的插件、扩展和第三方库,可以满足各种不同的需求。开发人员可以根据框架的约定进行开发,减少了沟通和协调的成本,提高了开发效率。 常见的框架有Web开发框架、移动应用开发框架、游戏开发框架等。例如,Web开发框架中常见的有Spring、Django、Express等,它们提供了处理HTTP求、数据库操作、前后端分离等功能。移动应用开发框架常见的有React Native、Flutter等,可以用于跨平台应用的开发。游戏开发框架如Unity、Cocos2d-x等,提供了游戏逻辑、渲染、物理引擎等功能。 总之,框架是一种具有良好结构和通用功能的软件模板,可以加速开发、提高可维护性,并且与其它工具和库相互配合,形成一个完整的开发环境。通过使用框架,开发人员可以更专注于实现独特的业务逻辑,而无需关注底层的细节和复杂性。 ### 回答3: 框架framework)是一种开发的基础结构和编程环境,提供了一套编程接口和工具,方便开发者快速构建和部署应用程序。它提供了一系列的库、模板、工具和规范,用于解决特定领域的常见问题。 框架对开发者来说有很多好处。首先,框架提供了一种结构化的方法来组织和管理代码,使得开发过程更加规范和高效。开发者可以根据框架提供的规范和约束进行开发,从而减少重复劳动,提高开发效率。 其次,框架通常提供了一些常用的功能和组件,如数据库访问、用户认证、缓存管理等,开发者可以直接使用这些功能来减少开发工作量。同时,框架还提供了一些现成的模板和样式,用于快速创建用户界面,加快开发速度。 另外,框架还能够提高应用程序的可维护性和可扩展性。框架的结构和规范使得代码更加模块化和可重用,便于团队合作和后续维护。而且,由于框架提供了一种标准的开发方式,开发者之间可以更容易地共享和交流经验,提高开发质量。 总之,框架是一种帮助开发者快速构建应用程序的工具和环境,它提供了一套结构化的方法和常用功能,加速开发过程,并提高应用程序的质量和可维护性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值