一、Activity
什么是 Activity?
Activity 是 Android 四大组件之一,承担着用户界面交互的核心职责。由于移动端应用涉及前后台切换、旋转、内存回收、任务栈管理等复杂情况,理解 Activity 的生命周期对于开发健壮的应用至关重要。
每个 Activity 都有一个窗口,该窗口可以全屏幕填充,也可以是一个小窗口浮动在其他窗口上。
一个应用程序通常由多个 Activity 组成,它会指定应用程序中的某个 Activity 作为主 Activity,这意味着当用户第一次启动应用程序时呈现给用户的活动,并且 Activity 可以相互跳转来执行不同的操作。
生命周期
一个 Activity 从创建到销毁,大致会经历以下主要方法:
onCreate():初始化逻辑:加载布局、初始化 ViewModel/数据源、注册监听等;
onStart():Activity 对用户可见,但还不能交互;
onResume():Activity 进入前台、获取焦点,用户可交互;
onPause():Activity 暂停,失去焦点(如弹出 Dialog 或跳转新界面)。适合保存少量数据、停止动画/传感器等;
onStop():Activity 对用户完全不可见。此时应释放较重的资源(如摄像头、传感器、广播);
onDestory():Activity 即将销毁,用于释放最后的资源,解绑引用避免内存泄漏。

可结合官方文档中的经典图示,可以发现:
onResume → onPause 属于前台可交互与失去焦点的切换;
onStart → onStop 属于可见与不可见的切换;
onCreate → onDestory 属于整个 Activity 的完整生命轨迹。
典型场景下的生命周期流程:
启动 Activity A:onCreate → onStart → onResume
在 A 页面打开新的 Activity B 时:
A:onPause → onStop
B:onCreate → onStart → onResume
按下返回键,返回 A 页面时:
A:onRestart → onStart → onResume
B:onPause → onStop → onDestory
按下 Home 键切换到桌面时,A:onPause → onStop
从桌面再次打开软件时,A:onRestart → onStart → onResume
打开任务栏时,A:onPause → onStop
从任务栏杀掉当前应用时:会直接杀死整个应用进程,不是正常销毁 Activity,因此不会产生生命周期回调。
Activity 启动方式
Android 提供了四种启动模式(LaunchMode),用于控制 Activity 在 任务栈(Task Stack) 中的行为。
从 Launcher(桌面应用)启动应用时,应用的第一个 Activity(通常是 MainActivity)会放到一个新的任务栈里。每个 Activity 可以设置不同的启动方式:
standard(默认):每次启动都会创建新的实例并入栈,适合大多数页面;
singleTop:如果目标 Activity 已位于栈顶,则复用该实例,并调用
onNewIntent(),如果不在栈顶,则新建实例;singleTask:栈内只会存在一个实例,如果已存在则直接复用,并清除其上的其他 Activity。适合主页、搜索页等需要唯一入口的页面;
singleInstance:独立运行在一个新的任务栈中,并且该栈中只允许存在此一个 Activity。典型应用:闹钟、来电界面等全局独立页面。
搭建一个 A1 → B → A2 → A3 的页面切换场景(A1、A2、A3 表示同一个 Activity A),观察不同启动模式下的情况:
standard:B 启动的 A2 页面是新建的,A2 启动的 A3 也是新建的,从 A3 返回时:A3 → A2 → B → A1;
singleTop:B 启动 A2 时,A1 存在与任务栈中,但不是栈顶,所以 A2 页面是新建的。从 A2 启动 A3 时,A2 已经是栈顶,所以 A3 会复用 A2(不会新建),生命周期回调为:onPause → onNewIntent → onResume。返回时:A3 → B → A1
singleTask:从 A1 启动 B 页面时是常规情况(A1 到 onStop,B 到 onResume),后面的情况略有不同:
B 启动 A2 页面:由于任务栈中已经存储 Activity A 的实例了,因此会将 A 页面移至栈顶(onRestart → onStart → onNewIntent → onResume),B 页面会被弹出任务栈销毁(onPause → onStop → onDestory)。
A2 启动 A3 页面:和 singleTop 一样,Activity A 实例已经存在与栈顶了,不会创建新页面,直接复用(onPause → onNewIntent → onResume)。
singleInstance:Activity A 是单独的任务栈且只有一个实例。
B 启动 A2 页面:重新启动 A 页面(onRestart → onStart → onNewIntent → onResume),B 页面被暂停(onPause → onStop)
A2 启动 A3 页面:和 singleTop 一样,Activity A 实例已经存在与栈顶了,不会创建新页面,直接复用(onPause → onNewIntent → onResume)。
A3 返回时:A 页面从自己的任务栈中弹出被销毁(onPause → onStop → onDestory),B 页面重新启动(onRestart → onStart → onResume)。
Activity 的启动流程
todo...
二、Service
什么是 Service?
Service 是 Android 中四大组件之一,它是一种没有界面、可以在后台长期运行的组件。常见场景包括:
音乐播放器:即使切换到其他应用,后台依然能播放音乐;
文件下载:退出应用后仍可保持下载任务;
长连接:即时通讯类应用会在后台维持连接,接收消息。
创建 Service 的基本方式:
// 创建类继承 Service
class MyService : Service() {
override fun onBind(intent: Intent?): IBinder? {
return null // 普通启动服务返回 null
}
}然后在 AndroidManifest.xml 中配置:
<application>
<service
android:name=".MyService"
android:enabled="true"
android:exported="false" />
</application>Service 的生命周期
核心的回调方法:
onCreate():首次创建时调用,一次性初始化。onStartCommand():每次调用startService()都会触发。onBind():当使用bindService()时触发,返回一个Binder对象。onUnbind():调用unbindService()解除绑定时调用。onDestroy():销毁时调用,用于释放资源。
服务的两种启动方式
startService()
当调用 startService() 方法时表示启动服务。
生命周期流程是:
onCreate()(仅执行一次)→onStartCommand(),每调用一次startService(),onStartCommand()都会执行一次;Service 会一直运行,直到调用
stopService()或stopSelf(),生命周期进入onDestroy();不能与 Activity 通信,适合执行后台任务(如音乐播放、下载)。
val intent = Intent(this, MyService::class.java)
startService(intent)bindService()
startService() 方法表示绑定服务。
每次调用
bindService(),系统都会尝试和目标Service建立一个绑定关系,如果Service还没有启动,会先触发onCreate(),然后触发onBind()返回一个 IBinder 对象可以与 Service 进行通信;
同一个 Activity/Fragment 对同一个 Service 多次调用
bindService(),系统会复用已有的连接,不会重复创建新的 Service 实例。绑定服务适合需要与 Service 通信的场景,如音乐播放器的播放/暂停控制;
val intent = Intent(this, MyService::class.java)
bindService(intent, connection, Context.BIND_AUTO_CREATE)通过 ServiceConnection 获取 Service 返回的 Binder 对象:
private val connection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, binder: IBinder?) {
val myBinder = binder as MyBinder
myBinder.doSomething()
}
override fun onServiceDisconnected(name: ComponentName?) {}
}注意:默认的 Service 是本地服务,所有生命周期回调运行在应用的主线程(UI 线程),如果要执行耗时操作,必须配合子线程(如
Thread、HandlerThread、ExecutorService、Coroutine)使用,否则会导致 ANR。
远程服务
远程服务独立于主进程,是一个独立的进程。不受其他进程的影响,多个进程都可以通过 AIDL(跨进程通信方式)单独与该服务进行 IPC 通讯,因此较为复杂,且这种服务一般长期运行在后台。典型的例子就是系统服务。
前台服务
从 Android 8.0 (API 26) 开始,如果应用需要在后台长时间运行(如音乐播放、导航、健康监测),必须使用前台服务(Foreground Service),否则会因为系统限制而被回收。
前台服务必须在服务启动后 5 秒内调用
startForeground(),并显示一个常驻通知;优先级高,不容易被系统杀死。
class MusicService : Service() {
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val notification = NotificationCompat.Builder(this, "music_channel")
.setContentTitle("正在播放")
.setContentText("音乐名 - 歌手")
.setSmallIcon(R.drawable.ic_music_note)
.build()
startForeground(1, notification)
return START_STICKY
}
override fun onBind(intent: Intent?): IBinder? = null
}
三、BroadcastReceiver
什么是 BroadcastReceiver?
在安卓系统中有广播消息,可以由系统、应用程序或其他组件发出。广播接收器(BroadcastReceiver)就是一种用于接收和响应广播消息的组件。
广播的分类
Android 中的广播主要可以分为两种类型:
标准广播:在广播发出之后,所有的 BroadcastReceiver 几乎会在同一时刻收到这条广播消息,因此它们之间没有任何先后顺序可言。
有序广播:是一种同步执行的广播,在广播发出之后,同一时刻只会有一个 BroadcastReceiver 能够收到消息,等待逻辑处理完毕之后,广播才会继续传递。此时的 BroadcastReceiver 是有先后顺序的,且前面的 BroadcastReceiver 可以截断正在传递的广播,这样后面就无法收到广播消息了。
静态/动态注册广播
静态注册不受 app 是否运行所影响,即使 app 没有运行,app 里静态注册的广播接收者也可以接收广播,因此比较耗电,占内存。适合长时间监听广播,如系统广播。
动态注册的广播在组件结束之前,也会随之结束(当然是手动注销的),适合只在特殊时刻监听广播。
动态注册的优先级高于静态广播。
本地广播
本地广播用于应用内部传递消息,比 BroadcastReceiver 更加高效和安全。
与 BroadcastReceiver 是以 Binder 通讯方式为底层实现的机制不同,众所周知 Binder 是跨进程的。
而 LocalBroadcastManager 是利用应用内部的 Handler 来实现,只是利用到了 IntentFilter 的 match 功能,因为是 Handler 实现的应用内的通信,自然安全性更好,效率更高。
四、ContentProvider
Android 出于安全考虑,每个应用运行在独立的沙箱中,默认无法直接访问其他应用的数据。
ContentProvider 它提供了一套完整的机制,允许一个程序访问另一个程序中的数据,同时还能保证被访问数据的安全性。目前,使用 ContentProvider 是 Android 实现跨程序共享数据的标准方式。
ContentProvider 的用法一般有两种:
一种是使用现有的 ContentProvider 读取和操作其他程序中的数据;
另一种是创建自己的 ContentProvider,给程序的数据提供外部访问接口。