一、Android 系统架构
Android 系统整体上可以分为五层结构,从上到下依次是:应用层、应用框架层、系统运行库层、硬件抽象层以及 Linux 内核层。下图展示了经典的 Android 架构分层图:

应用层(System Apps)
应用层包含系统自带的应用(如电话、短信、设置等)以及用户安装的第三方应用。这一层主要负责与用户进行交互,通常使用 Java/Kotlin 编写。我们日常开发的 App 就属于这一层。
应用框架层(Java API Framework)
应用框架层为开发者提供了构建应用所需的 API 接口。无论是系统应用还是用户应用,都需要通过调用这一层的 API 来实现功能。应用框架层由 Java 代码编写,因此也常被称为 Java Framework。下面列举了这一层所提供的主要组件:
Activity Manager:管理各个应用程序生命周期,以及常用的导航回退功能;
Location Manager:提供地理位置和定位功能服务;
Window Manager:管理所有开启的窗口程序;
Content Provider:使得不同应用程序之间可以共享程序;
系统运行库层(Native)
系统运行库层分为两个部分,分别是 C/C++ 程序库和 Android 运行时库。
C/C++:包括 OpenGL、SQLite、Libc 等,为上层框架提供底层能力;
Android 运行时库
核心库:提供了 Java 语言核心库;
ART 虚拟机:相比传统 JVM,ART 针对移动设备进行了优化。在应用安装时,ART 会执行一次预编译(AOT, Ahead Of Time),将字节码转为本地机器码并存储起来,从而提升运行效率。
硬件抽象层(HAL)
硬件抽象层位于内核与硬件驱动之间,向上层提供统一接口。它的作用是屏蔽底层硬件差异,让上层无需关心硬件细节,就能通过统一 API 调用不同厂商的硬件功能。
Linux 内核层(Linux Kernel)
Android 的核心系统服务基于 Linux 内核,在此基础上添加了部分 Android 专用的驱动。系统的安全性、内存管理、进程管理、网络协议栈和驱动模型等都依赖于该内核。
二、Android 系统启动流程
启动电源:当电源按下时引导芯片代码从预定义的地方(固化在 ROM)开始执行。加载引导程序 BootLoader 到 RAM 中,然后执行;
BootLoader:引导程序 BootLoader 是在 Android 操作系统开始运行前的一个小程序,它的主要作用是把系统 OS 拉起来并运行;
Linux 内核启动:当内核启动时,设置缓存、被保护存储器、计划列表、加载驱动。在内核完成系统设置后,它首先在系统文件中寻找 init.rc 文件,并启动 init 进程;
init 进程:主要用来初始化和启动属性服务,也用来启动 Zygote 进程。
Zygote 进程:创建 Java 虚拟机并为 Java 虚拟机注册 JNI 方法,创建服务器端 Socket,启动 SystemServer 进程;
SystemServer 进程:启动Binder 线程池,和 SystemServiceManager,并且启动各种系统服务;
Launcher 启动:被 SystemServer 进程启动的 AMS 会启动 Launcher,它启动会将已安装应用的图标显示到界面上。
三、App 启动流程
启动一个 App 的过程可以分为两个阶段:先启动应用进程,再启动根 Activity。根 Activity 通常是用户点击应用图标后展示的第一个页面,因此它的启动流程也可以视作应用启动的流程。
下图展示了从桌面点击图标后启动 App 的流程图:

1. Launcher 请求 AMS
当系统启动后,Launcher 会将已安装 App 的快捷图标展示在桌面上。这些图标就是应用根 Activity 的入口。
当用户点击某个 App 图标时,Launcher 会通过 ActivityManager.getService() 获取 AMS 的代理对象,并调用其 startActivity() 方法,请求 AMS 启动对应的根 Activity。
这里的通信底层是通过 AIDL 实现的,也就是说,Launcher 与 AMS 之间是基于 Binder 的跨进程调用。
2. AMS 启动应用进程
AMS 收到请求后,会先检查目标应用的进程是否已经存在:
如果进程不存在:AMS 会请求 Zygote 进程启动新的应用进程。Zygote 在 Java 框架层维护着一个 Socket 服务端,专门用于接收 AMS 的请求。当收到创建进程的请求后,Zygote 会通过 fork 自身来创建新的应用进程。通过这种方式创建的新进程可以直接继承 Zygote 已经初始化好的运行环境,比如虚拟机实例和 Binder 线程池,从而提升应用启动效率。
如果进程已存在:AMS 会直接进入下一步,通知该进程去启动目标 Activity。
3. AMS 与 ApplicationThread 通信
AMS 运行在 SystemServer 进程中,它会通过 Binder 通道与应用进程进行通信。当需要启动 Activity 时,AMS 会调用应用进程中的 ApplicationThread。
需要注意的是,ApplicationThread 是 ActivityThread 的内部类,负责接收 AMS 下发的各种启动指令(如启动 Activity、启动 Service 等)。
4. ActivityThread 启动 Activity
当 ApplicationThread 收到 AMS 的启动 Activity 请求后,会将任务切换到主线程执行。具体来说,它会向内部的 mH(ActivityThread.H 类)发送消息。
H 是继承自 Handler 的类,绑定在主线程的 Looper 上;
由于 ApplicationThread 是一个 Binder 对象,Binder 方法回调运行在 Binder 线程池中,所以需要借助 H 将任务切换回主线程,确保 UI 相关逻辑运行在主线程中。
最终,ActivityThread 会通过反射调用 Activity 的生命周期方法,完成根 Activity 的启动,用户就能看到应用界面。
四、设计模式使用案例
观察者模式
定义一种一对多的依赖关系,当一个对象的状态发生变化时,所有依赖它的对象都会自动收到通知并更新。
Android 中的
View.setOnClickListener()就是观察者模式,按钮点击事件发生时,注册的监听器(观察者)会被通知。
装饰器模式
在不改变原有对象的前提下,动态地给对象添加额外的功能。强调包装而不是继承,避免类爆炸。
Java IO:
BufferedInputStream装饰了InputStream,在原始读写功能上增加了缓存,提高效率。Java 集合:
Collections.synchronizedList()方法装饰一个 List,在原有方法的基础上增加了 synchronized 关键字,实现线程安全。
建造者模式
将一个复杂对象的构建过程与它的表示分离,使得同样的构建过程可以创建不同的表示。解决构造函数参数过多、可选参数复杂的问题。
StringBuilder:通过链式调用一步步构建字符串;
安卓中的 AlertDialog.Builder:通过
setTitle(),setMessage(),setPositiveButton()等方法,最后create().show();okHttp:
OkHttpClient、Request都是 Builder;
策略模式
定义一系列算法,把它们封装起来,使得它们可以互相替换,客户端可在运行时选择不同的算法。强调行为可替换。
排序算法:Java 的
Comparator,可以传入不同的比较策略,达到不同的排序效果。支付系统:不同支付方式(支付宝、微信、银行卡)可以抽象为不同策略,统一接口
pay(),在运行时根据用户选择切换。
五、MVC、MVP、MVVM
案例需求
我们先通过一个简单的案例来说明问题:根据输入框内容查询用户账号,并展示查询成功或失败的结果。
如果没有使用任何架构设计,那么通常会把所有逻辑都写在 Activity 里,包括:
业务逻辑处理(响应 Button 的点击事件,处理业务逻辑);
获取用户的输入(EditText 中的内容);
查询账号数据:向数据层请求用户信息;
展示结果:根据成功/失败更新 UI。
class NormalActivity : AppCompatActivity() {
val mTvResult: TextView by lazy { findViewById(R.id.tv_result) }
val editText: EditText by lazy { findViewById(R.id.et_account) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_normal)
/**
* 业务逻辑代码
*/
findViewById<Button>(R.id.btn_get_account).setOnClickListener {
getAccountData(getUserInput(), object : MCallback{
override fun onSuccess(account: Account) {
showSuccessPage(account)
}
override fun onFailed() {
showFailedPage()
}
})
}
}
// 获取用户输入
fun getUserInput(): String {
return editText.text.toString()
}
// 展示成功页面
fun showSuccessPage(account: Account) {
val text = "用户账号:${account.name},用户等级:${account.level}"
mTvResult.text = text
}
// 展示失败页面
fun showFailedPage() {
mTvResult.text = "获取数据失败"
}
// 查询用户数据
fun getAccountData(accountName: String, mCallback: MCallback) {
if (Random.nextBoolean()) {
val account = Account(accountName, 100)
mCallback.onSuccess(account)
} else {
mCallback.onFailed()
}
}
}从这个例子可以看到:当不使用任何架构时,Activity 会变得非常臃肿。它既要关心界面渲染,又要操心数据获取和业务逻辑,所有功能都耦合在一个类中。随着需求增加,代码会越来越复杂,维护成本也会越来越高。
因此,我们需要引入 MVC、MVP、MVVM 等分层架构,将不同的职责拆分到不同模块:
UI 层只负责界面展示;
逻辑层负责业务处理;
数据层负责数据获取。
这种分层方式能够有效降低耦合度,让代码更加清晰、易维护。
MVC 模式
Controller:Activity、Fragment;
View:layout、View 控件;
Model:数据处理(网络请求,SQL查询等)。

MVC 架构的流转过程是:用户点击某个 View 控件,事件传递到 Activity 中响应点击事件,通知 Model 层进行数据处理,Model 层处理完毕后通知 View 更新 UI。
如果使用 MVC 实现需求,各个模块需要处理的内容如下:
Activity(Controller 层):
业务逻辑处理
获取用户输入
展示成功/失败界面
Model 层:查询账号数据
View 层:layout(布局)
Controller 层(Activity)代码如下:
class MVCActivity : AppCompatActivity() {
val textView: TextView by lazy { findViewById(R.id.tv_result) }
val editText: EditText by lazy { findViewById(R.id.et_account) }
val mvcModel = MVCModel() // Activity 持有 Model 层的引用
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_normal)
// 业务逻辑代码
findViewById<Button>(R.id.btn_get_account).setOnClickListener {
// 通知 Model 层处理数据,通过回调通知 View 层
mvcModel.getAccountData(getUserInput(), object : MCallback {
override fun onSuccess(account: Account) {
showSuccessPage(account)
}
override fun onFailed() {
showFailedPage()
}
})
}
}
// 获取用户输入
fun getUserInput(): String {
return editText.text.toString()
}
// 展示成功页面
fun showSuccessPage(account: Account) {
val text = "用户账号:${account.name},用户等级:${account.level}"
textView.text = text
}
// 展示失败页面
fun showFailedPage() {
textView.text = "获取数据失败"
}
}Model 层代码如下:
// Model 层
class MVCModel {
// 查询用户数据
fun getAccountData(accountName: String, mCallback: MCallback) {
if (Random.nextBoolean()) {
val account = Account(accountName, 100)
mCallback.onSuccess(account)
} else {
mCallback.onFailed()
}
}
}通过代码可以发现,Controller 层(Activity)通过持有 Model 层的引用实现和 Model 层的通信,Model 层通过回调通知 View 层更新 UI 界面。
MVC 架构在日常的代码中使用还是比较多的,它的优缺点如下:
优点:一定程度上实现了 Model 层与 View 层的分离,降低了代码的耦合性;
缺点:在 Android 中,Controller 层与 View 层难以完全解耦,随着项目复杂度的提升,Controller(Activity)将会越来越臃肿。
对于 MVC 模式,有的模型图如下图所示,因为 View 和 Controller 难以完全分离。

MVP 模式
MVP 即 Model-View-Presenter 模型。
View:视图层(Activity);
Model:数据处理(网络请求,SQL查询等);
Presenter:中间层,负责业务逻辑处理,以及和 View/Model 层的通信。

如果使用 MVP 实现需求,各个模块需要处理的内容如下:
View 层(Activity):
获取用户输入
展示成功/失败界面
Model 层:查询账号数据
Presenter 层:业务逻辑处理,同时负责和 View/Model 层的通信
在 View 层首先创建对应的接口,定义需要实现的功能(获取用户输入、展示界面等):
interface IMvpView {
fun getUserInput(): String
fun showSuccessPage(account: Account)
fun showFailedPage()
}Model 层不变,还是处理数据的逻辑:
class MvpModel {
// 查询用户数据
fun getAccountData(accountName: String, mCallback: MCallback) {
if (Random.nextBoolean()) {
val account = Account(accountName, 100)
mCallback.onSuccess(account)
} else {
mCallback.onFailed()
}
}
}Presenter 层同时持有 View 层和 Model 层的引用,以及对业务逻辑的处理:
class MvpPresenter(
val view: IMvpView // View 层的实例通过构造参数传递
) {
// Model 层的实例直接创建对象
val model: MvpModel = MvpModel()
// 业务逻辑处理
fun getData(accountName: String){
// 通过 Model 层处理数据
// 通过 View 层更新 UI
model.getAccountData(accountName, object : MCallback {
override fun onSuccess(account: Account) {
view.showSuccessPage(account)
}
override fun onFailed() {
view.showFailedPage()
}
})
}
}让 Activity 实现该 IMvpView 接口,以提供 View 层的功能。在按钮点击后通知 Presenter 层处理业务逻辑。
class MVPActivity : AppCompatActivity(), IMvpView{
val textView: TextView by lazy { findViewById(R.id.tv_result) }
val editText: EditText by lazy { findViewById(R.id.et_account) }
val presenter = MvpPresenter(this) // 持有 Presenter 引用
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_normal)
// 点击按钮时通知 Presenter 进行具体的业务逻辑处理
findViewById<Button>(R.id.btn_get_account).setOnClickListener {
presenter.getData(getUserInput())
}
}
// 获取用户输入
override fun getUserInput(): String {
return editText.text.toString()
}
// 展示成功页面
override fun showSuccessPage(account: Account) {
val text = "用户账号:${account.name},用户等级:${account.level}"
textView.text = text
}
// 展示失败页面
override fun showFailedPage() {
textView.text = "获取数据失败"
}
}MVP 与 MVC 的差别
Model 不再于 View 直接进行通信,而是通过中间层 Presenter 来实现;
Activity 的功能被简化,不再充当控制器,主要负责 View 层面的工作。
MVP 的优缺点
优点:解决了 MVC 中 Controller 与 View 过度耦合的缺点,职责划分明显,更加易于维护;
缺点:接口数量多(Presenter、Model 层也可以定义接口),随着项目复杂度的升高,Presenter 层会越来越臃肿。
使用 MVP 的建议
接口规范化,封装父类接口以减少接口的使用量;
使用第三方插件自动生成 MVP 代码;
对应一些简单的界面,可以选择不使用框架;
根据项目的复杂程度,部分模块可以选择不使用接口。
MVVM 模式
什么是 MVVM 模型?
MVVM 是 Model-View-ViewModel 的简写,MVVM 在 MVP 的基础上实现类数据视图的绑定(DataBinding),当数据变化时,视图会自动更新;反之,当视图发生变化时,数据也会自动更新。

使用 MVVM 模式实现需求,各层的功能划分如下:
View 层(Activity、layout 布局文件):获取用户输入、展示成功/失败界面;
ViewModel 层:业务逻辑处理、数据更新(通过 DataBinding);
Model 层:查询账号数据。
View 层主要包括 layout 文件和 Activity,layout 文件需要设置为 databinding 布局,定义 ViewModel 层的对象,在布局中使用里面的数据。
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="viewModel"
type="top.tonydon.interview.mvvm.mvvm.MvvmViewModel" />
</data>
<LinearLayout
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".normal.NormalActivity">
<EditText
android:id="@+id/et_account"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:text="@={viewModel.userInput}"
android:hint="请输入要查询的账号" />
<Button
android:id="@+id/btn_get_account"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="50dp"
android:text="获取账号信息" />
<TextView
android:id="@+id/tv_result"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="50dp"
android:text="@{viewModel.result}"
android:hint="账号信息未获取" />
</LinearLayout>
</layout>然后是 Activity,需要使用 DataBindingUtil 设置布局,完成 ViewModel 的创建、变量初始化、点击事件通知 ViewModel 层处理。
class MvvmActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 通过 DataBindingUtil 设置 ContentView,返回一个 ActivityMvvmBinding 实例(系统自动生成)
val binding: ActivityMvvmBinding =
DataBindingUtil.setContentView(this, R.layout.activity_mvvm)
// 创建 ViewModel 对象绑定到 layout 中
val viewModel = MvvmViewModel(application)
binding.viewModel = viewModel
binding.btnGetAccount.setOnClickListener {
viewModel.getData()
}
}
}ViewModel 层一般持有 Model 层的引用和 DataBinding,实现向双方的通信。通过 ObservableField 等手段,更新变量值时可以自动更新 UI 界面。
// 一般需要传入 Application 对象,方便在 ViewModel 中使用 Application
class MvvmViewModel(
val application: Application
) {
var userInput = ObservableField("") // 和 View 层双向绑定
var result = ObservableField("") // 和 View 层单向绑定
val model = MvvmModel() // 持有 Model 层引用
fun getData() {
model.getAccountData(userInput.get()!!, object : MCallback {
override fun onSuccess(account: Account) {
val text = "用户账号:${account.name},用户等级:${account.level}"
result.set(text)
}
override fun onFailed() {
result.set("获取数据失败") // 设置时自动更新 UI
}
})
}
}Model 层与其他模式相同,进行数据处理即可:
class MvvmModel {
// 查询用户数据
fun getAccountData(accountName: String, mCallback: MCallback) {
if (Random.nextBoolean()) {
val account = Account(accountName, 100)
mCallback.onSuccess(account)
} else {
mCallback.onFailed()
}
}
}注:MVVM 模式在 Android 中想要使用的完美需要搭配 LiveData + ViewModel 实现,上述代码只是作为了解 MVVM 模式的案例,并不是最佳实践。
MVVM 与 MVP 的区别
减少了接口数量;
告别了繁琐的
findViewById()操作;
MVVM 的优缺点
优点:实现了数据和视图的双向绑定,极大的简化代码;
缺点:bug 难以调试,并且 DataBinding 目前现在还存在一些编译问题。
三种模式的对比
MVC:学习简单,但是解耦不够彻底;
MVP:解耦更加彻底,学习起来也相对比较简单,但是代码相对比较繁琐;
MVVM:代码逻辑非常简洁,但是学习成本较大。
六、APK 打包流程和反编译
内存优化、卡顿优化