《Android开发精要》读书笔记——Android应用模型

来源:互联网 发布:照片编辑软件 编辑:程序博客网 时间:2024/06/05 02:00

Android应用模型的设计思想取自于web2.0的Mashup概念,是基于组件的应用设计模式。在该模型下,每个应用都由一系列的组件搭建而成,组件通过应用的配置文件描述功能。Android依照组件的配置信息,了解各个组件的功能并进行调度。
Android中有四大组件,分别是界面组件Activity、服务组件Service、数据源组件Content Provider以及触发器组件Broadcast Receiver。每个Android应用,大到功能庞大的浏览器应用,小到入门必学的“Hello World”,都由这四类组件共同搭建而成。

1. 基于Mashup的应用设计

1.1 Android中的Mashup

Android中的Mashup,是将应用切分成不同类型的组件,通过统一的定位模型和接口标准将它们整合在一起,来共同完成某项任务。

1.2 基于Mashup的Android应用模型

在Mashup的概念下构造Android应用,有三个基本要素:组件(Component)、连接和配置。
组件
组件就是特定功能和接口规范的实现单元。
每类组件都有着不同的设计目标,或者负责界面展示,或者负责后台服务,或者负责数据提供,或者负责事件监听。
从代码来看,组件就是派生自特定接口或基类的子类实现。比如,界面组件Activity,就是拍生子android.app.Activity类的子类实现。
每个Android组件都是一个黑盒模块。它们依照系统设计的接口和规范实现相关的功能。
组件的构造、销毁等生命周期管理工作,都是由Android中的组件管理服务统一负责。它了解所有组件的功能和特征,会选择合适的时机构造和销毁所需的组件。

连接
连接是一个抽象的概念,指的是组件与组件之间的通信信道,是Android为不同类别的组件之间进行调用和通信预设的模式。
它的实现方式根据连接两端组件类别的不同而有所变化。比如,与界面组件的通信连接,需要通过Intent(android.content.Intent)对象来建立;而与数据源组件的通信,则通过URI地址来定位并搭建连接通路。
连接的构造,是由请求连接的组件、被连接的实现组件和组件管理服务共同维护的。请求连接的组件需要按照规范描述出所需的组件的类型和特征;实现组件,同样需要依照规范描述出它们的功能,并完成对应功能的实现;而组件管理服务会依照请求者的描述找到符合的实现组件。

配置
配置是用来描述组件的功能和实现特征的信息。
在Android中,每个应用都由名为AndroidManifest.xml的配置文件,其中包括了该应用中所有组件的相关信息,包括组件的名称、类型、能够处理的数据格式、所需的全县信息等。
Android的组件管理服务,就是通过配置文件中的信息去了解每个组件的特征。因此,一个组件只有将相关信息写入了配置文件,才会被系统服务认知,继而又被调用的机会。
我们通过发送邮件的例子,来进一步介绍组件、连接、配置以及基于Mashup的组建模型。
这里写图片描述

1.3 基于Mashup的应用架构特征

基于Mashup的应用,其核心是组件,应用边界、进程边界和网络边界在Android中都变得模糊而且不那么重要了。在Android中,组件执行时的聚合单元是任务(Task),每个任务都由若干个界面组件对象构成,这些组件可能来自不同的应用,运行在不同的进程中,它们彼此独立,就像黑盒子一样,无需关注具体调用者或被调用者的实现细节。组件间的数据传输,都是通过消息、进程间的通信模型等序列化数据传输的方式来进行,而不是通过对象指针的直接传递,这就使得Android的应用天生具有了良好的跨进程特征。在实际的Android开发中,开发者通常不需要关注应用进程的问题,而只需要把精力放在组件的管理和控制上即可。
基于组件的设计,不仅使得应用具有跨进程性,而且还具有跨网络的特性。当调用方组件发起请求,希望第三方组件帮助提供所需的功能或数据时,能够响应该请求的,不仅可以是一个本地已安装应用的组件,还可以是符合该请求的web页面,C/S和B/S的差别在Android上也变得模糊了。

2. 界面组件Activity解析

Android的界面组件并没有沿用传统的客户端常用的MVC架构,它的设计理念更接近于Web页面。毕竟,Android应用的架构思想就源自于Web 2.0中Mashup的概念。
界面组件Activity与Web页面相比,在设计理念上,有如下相似之处:
1. 从运行模式来看,Web页面之间通过链接进行连接,从一个页面调到另一个页面或回退到前一个页面,从而构成了一个页面栈。在浏览器中,用户可能会打开多个这样的页面栈。但同时与用户进行交互的,只有某个页面栈的当前页面。
与之类似,Android是个多任务的操作系统。它的上面可以同时运行多个任务。每个任务都有一个界面组件栈,栈中的元素是界面组件对象的实例,其中负责与用户进行交互的是前台任务的栈顶组件。
2. 每个Web页面都会由一个或多个URL进行定位,而页面间的切换和数据传输都需要通过服务器进行处理。
同样,Android的界面组件也是通过类型信息、数据URI信息、数据类型信息等描述信息进行定位的。而界面组件的切换和数据传输,都依赖于Android组件管理服务的统一调度和传递。
3. Android界面组件的功能设计和Web页面类似,都近似于功能黑盒。其行为主要取决于其输入的信息,受外部环境影响不大。完全的黑盒性质会导致一些共享数据的传输变得极其困难。因此,在Web开发中,会通过Cookie来存储一些状态信息,通过破坏一定的黑盒特征,来换取执行的效率。
而处于同样的设计考虑,Android的每个应用进程都有一个应用环境对象(Application Context)。小数据量的共享数据可以通过它来进行存储,从而避免因数据在界面组件间连续传递而增加的额外开销和复杂性。

3. 服务组件Service解析

Android的服务组件派生自android.app.Service类。
在功能概念方面,Android的服务组件和Windows等传统平台的服务比较接近,但是在运行模式和使用方式上却有很大的不同。
首先从运行模式上来看,Android的服务组件没有运行在独立的进程或线程中。
默认情况下,服务组件构造于应用进程中,并且和所有其他的Android组件一样,都在进程的主线程(UI线程)中运行。
这就意味着,如果直接在服务组件中同步执行耗时的操作,将会导致主线程阻塞或界面假死,从而无法响应用户的操作。
另外,从使用方式来看,Android的服务组件不仅可以与前端界面组件建立双向连接,提供数据和功能支持,也可以单向接受Intent对象的请求,进行数据的分析处理和功能调度。

3.1 服务组件的功能和特征

Android的界面组件,意在帮助应用与用户进行交互。而服务组件,则用于辅助应用与系统的其他组件或系统服务进行沟通。
服务组件可以扮演功能调度者,从事件触发器对象那里收集各类时间信息,进一步分析和处理,然后更新界面、修改数据抑或进行其他相关的操作,调度整个应用使其保持正确的状态。
除了作为调度者,服务组件还可以扮演另一个很重要的角色——界面组件的功能提供者。
和界面组件类似,不论是服务的绑定还是连接,服务组件的定位和消息的传递都是通过Android的意图机制来实现的。这使得服务的使用者和提供者彼此透明,服务组件可以动态地变更、增删和替换,大大增强了系统的灵活性。

3.2 服务器组件的进程间通信模型

当界面组件与服务组件绑定后,进程会通过方法的调用进行通信。而在实际应用中,前台界面组件和后台服务组件可能来自不同的应用,这就需要进行进程间通信。
Android的进程间通信和传统的远程通信模型非常相似,是典型的代理模式。如下图:
这里写图片描述

4. 触发器组件Broadcast Receiver解析

对于Android应用而言,不仅需要通过界面直接和用户打交道,及时处理用户的请求。还需要监听系统或系统中其他应用发生的事件,做出响应。
从实现来看,所谓的触发器组件,是派生自android.content.BroadcastReceiver的子类型,它的实现集中在BroadcastReceiver.onReceive方法中。

4.1 触发器组件的功能和特征

Android的触发器组件,在工作方式上更接近于函数,而不是对象。
典型的对象不仅包括算法逻辑,还包含一些用于存储数据的成员变量,但触发器组件对象被构造出来后,通常只执行BroadcastReceiver.onReceive方法,便结束了其生命周期。除了一些初始构造时传入的成员变量,其余都没有用武之地,不会有机会被用到。
和所有其他组件一样,触发器组件也是在应用进程的主线程中被构造,因此,其功能函数BroadcastReceiver.onReceive的执行必须是同步且快速的,否则会阻塞与用户交互的当前进程,影响用户的体验。
这里写图片描述

5. 数据源组件Content Provider解析

和其他组件不同,数据源组件并不包含特定的功能逻辑,而是负责为应用提供数据访问的接口
在Android中,除了放在扩展存储设备等共享目录中的数据,各个应用所有的数据库、文件、资源信息等内容都是私有的,其他应用没有权限直接访问。
这样的权限设计,保证了各个应用的独立性和安全性,避免应用所依赖的关键数据暴露或被破坏。
但在很多场景下,应用间的数据交互还是很有必要的。比如联系人应用就应该允许第三方应用使用其中的数据,对联系人的信息进行查询、选择和修改等。数据源组件,正是为了帮助在Android的各个应用间共享数据而设计的。

5.1 数据源组件的定位和操作

数据源组件派生自抽象类android.content.ContentProvider,需要实现其中的query,update,insert,delete等抽象接口。
数据源组件中数据存储的方式没有任何限制,可以通过数据库、文件等任意方式来实现(甚至是直接从其他数据源获取)。
整个数据源组件的接口设计集合了REST标准和数据库设计的概念,它通过URI(Uniform Resource Identifier)进行定位,像数据库一样,通过SQL语句描述具体的操作。

5.2 数据源组件的开发

与其他组件不同,数据源组件没有使用Android的意图机制。
数据源组件与其他组件相同,都构造于应用主线程中。直接对它进行数据的读写操作,可能会阻塞主线程,从而影响应用与用户的交互。因此,当设计大量的读写和查询时,需要开启一个后台线程,在线程中执行数据交互。

0 0