Android: 架构篇
Admin Lv3

同为Linux系操作系统,安卓与其他的兄弟姐妹们大相径庭。安卓是为嵌入式设备设计的,这些设备的各种资源比如内存、算力、电量都很紧张,这使得安卓除了系统内核外有着独特的软件架构

安卓系统层级结构

安卓可以被抽象成一个简略的层级结构

  • 内核层:针对嵌入式设备修改过的Linux内核,有特权的代码
  • 系统服务层:一大堆服务于系统的软件,比如驱动、内核模块、守护进程,以及一些编程常用的标准库
  • ARE层(Android Runtime Environment):提供安卓应用的运行环境,包括安卓开发用到的库
  • 应用层:用户能直接使用的应用

安卓应用解剖

和桌面应用的不同,安卓应用并不是一个简单的进程,也没有类似Javapublic static void main以及C++int main的程序入口。其结构更像是一个Web应用,由一堆散装的组件蓝图构成,然后由一个系统服务 – Zygote – 根据需要进行生成、管理以及销毁。

四大组件类型

Activity

每个Activity组件负责一个单独的可交互的UI页面,这些页面由一个个小部件构成。安卓只保证Activity在对应页面可见时存在。
Activity的生命周期长这样

onCreate
onStart
onDestroy
onResume
onPause
onStop
Created
Started
Destroyed
Running
  • onCreate:这个时间点页面刚刚被生成,适合初始化页面相关变量以及视图
  • onDestroy:页面实例被销毁,安卓不保证App退出的时候这个方法一定被调用,因为有时应用是直接被kill -9干掉的
  • onStart:页面已被绘制出来但无法接受用户输入,比如中间跳出弹窗或者其他app页面的时候
  • onResume:页面被聚焦且开始和用户交互了

Service

Service可以被看作成一个没有UI的Activity,但没有除了onCreated以及onDestroyed之外的方法
Service有两个子类 – Bounded Service 和 Started Service

Started Service

多用于完成一次性的任务,比如放个东西进数据库或者发个信息到网上

Bounded Service

类似Linux的pipe,安卓专属的IPC机制,提供一个半双工信道(支持双向传输但两个方向不能同时)– Binder – 来支持两个端点的通信,可跨应用

Broadcast Receiver

类似JS的事件侦听器,可以捕获重要的系统事件,比如可以在系统启动后广播的android.intent.action.BOOT_COMPLETED注册一个Receiver来实现开机自启

Content Provider

本质上是数据源(内容)上方的一层REST API,可以被用来共享一个打开的文件到另一个组件,有增删改查四个接口insert(), delete(), update(), query()外加一个内容数据类型查询getType()

Manifest文件

所有组件必须在一个叫AndroidManifest.xml的文件里声明,比如

1
2
3
4
5
6
7
8
9
10
<manifest ...>
<application
android:label="@string/app">
...>
<activity
android:name=".MyActivity"
android:label="@string/my">
</activity>
</application>
</manifest>

Context

Context是容纳Component或者是App的容器,可以在传参的时候用来指定组件和应用

Component Context

Activity和Service都继承于Context类,可以通过this直接获取目前组件实例对应的Context。此外,还可以通过startActivity()以及startService()等方法来唤醒其他的Activity或是Service

Application Context

在应用启动后会产生一个ApplicationContext单例,其生命周期与应用的生命周期相绑定,且在任意其他Context下都可以调用Context.getApplicationContext()被获取到。但与组件Context不同的是,其startActivity方法一般无法被用来唤醒Activity,强行调用会出现报错。
可以新建一个类去继承Application Context

1
2
3
class MyApp : Application() {
...
}

修改一下Manifest文件让系统知道这个class代表Application

1
2
3
4
5
6
7
<manifest ...>
<application
android:name=".MyApp"
...>
...
</application>
</manifest>

Intent

Intent可以被看作是组件之间交换信息的数据包,包含了发送方期望请求方完成的操作以及一些参数。比如在一个组件Context里唤醒另一个组件时就需要构建一个Intent

1
2
3
this.startActivity(
Intent(this, TargetActivity::class.java)
)

Intent可分为显式和隐式。显式Intent明确指定了需要互动的组件,比如在上面的例子里系统收到该请求后会找到并唤醒当前Context(this)从属的App中的TargetActivity组件。隐式Intent则不会对AppContext以及组件进行限定,而是通过其他组件在Manifest文件里声明的IntentFilter来发送给匹配的组件

1
this.startActivity( Intent(Intent.ACTION_EDIT) ) // 这里没有传入Context
1
2
3
4
5
6
7
8
<activity
android:name=".MyActivity"
android:label="@string/my">
<intent-filter>
<action
android:name="android.intent.action.EDIT" />
</intent-filter>
</activity>

MyActivity只响应操作为EDIT的Intent
隐式Intent的应用场景很常见,比如点开一个txt文件时安卓会弹窗询问要用哪个编辑器打开,这些出现的编辑器都声明了相关的IntentFilter