Appearance
Android 四大组件详解 📱
一、Activity(活动)
1.1 基本概念
Activity 是 Android 应用中负责用户界面交互的组件,每个 Activity 代表一个单独的屏幕窗口。
1.2 生命周期详解
┌─────────────┐
│ onCreate() │ → 初始化界面、数据
└──────┬──────┘
↓
┌─────────────┐
│ onStart() │ → 可见但不可交互
└──────┬──────┘
↓
┌─────────────┐
│ onResume() │ → 完全可见且可交互(前台)
└──────┬──────┘
↓
[用户操作]
↓
┌─────────────┐
│ onPause() │ → 失去焦点但还可见(部分被遮挡)
└──────┬──────┘
↓
┌─────────────┐
│ onStop() │ → 不可见(完全被遮挡)
└──────┬──────┘
↓
┌─────────────┐
│onDestroy() │ → 被销毁
└─────────────┘面试考点
Q1: Activity 生命周期的完整调用顺序?
A:
- 首次启动:
onCreate()→onStart()→onResume() - 暂时切换到后台:
onPause()→onStop() - 从后台回到前台:
onRestart()→onStart()→onResume() - 销毁:
onPause()→onStop()→onDestroy()
Q2: 四种启动模式(launchMode)的区别?
A:
| 模式 | 描述 | 典型场景 |
|---|---|---|
| Standard | 默认模式,每次启动都创建新实例 | 大多数普通 Activity |
| SingleTop | 栈顶复用,如果实例已在栈顶则调用 onNewIntent() | 启动页、搜索结果页 |
| SingleTask | 栈内复用,整个栈只有一个实例,会清除上面的 Activity | 浏览器首页、应用启动页 |
| SingleInstance | 独立栈,独占一个任务栈 | 来电界面、闹钟提醒 |
Q3: Intent 的四种类型?
A:
- Explicit Intent(显式): 指定具体组件类名
- Implicit Intent(隐式): 通过 Action、Data、Category 匹配
- Intercept Intent(拦截): 通过 Intent Filter 拦截
- Pending Intent(待处理): 授权其他应用使用自己的 Intent
Q4: Intent 传递数据的方式及限制?
A:
putExtra(): 传递基本数据类型、String、Serializable、Parcelable- Bundle 限制: 约 1MB(不同设备可能不同)
- 大量数据传递: 推荐使用 ViewModel、SharedPreferences、数据库
二、Service(服务)
2.1 基本概念
Service 是在后台执行长时间运行操作而不提供 UI 的组件。
2.2 启动方式对比
kotlin
// 方式 1: startService() - 启动型服务
startService(Intent(this, MyService::class.java))
// 方式 2: bindService() - 绑定型服务
bindService(Intent(this, MyService::class.java), connection, Context.BIND_AUTO_CREATE)生命周期对比
| 启动方式 | 生命周期 | 调用者死亡 | 典型场景 |
|---|---|---|---|
| startService() | onCreate() → onStartCommand() → onDestroy() | 继续运行 | 音乐播放、下载任务 |
| bindService() | onCreate() → onBind() → onUnbind() → onDestroy() | 服务停止 | 数据交互、ContentProvider |
2.3 面试考点
Q1: Service 和 Thread 的区别?
A:
- Service 不是独立线程:运行在主线程,需要耗时操作必须开启子线程
- 生命周期:Service 由系统管理,Thread 需要手动管理
- 使用场景:Service 适合跨组件调用,Thread 适合内部逻辑
Q2: Foreground Service(前台服务)的作用?
A:
- 通过通知栏显示,优先级更高
- 不易被系统杀死
- 必须调用
startForeground()显示通知 - 需要
FOREGROUND_SERVICE权限
Q3: Service 保活方案?
A:
- 前台服务:显示通知栏
- 闹钟保活:AlarmManager 定时重启
- JobScheduler:系统调度任务
- 互相启动:多个 Service 互相唤醒
- 监听系统广播:BOOT_COMPLETED、ACTION_SHUTDOWN
- Root 权限:最高级别(不推荐)
三、BroadcastReceiver(广播接收器)
3.1 分类
静态注册 vs 动态注册
kotlin
// 动态注册
val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
// 处理广播
}
}
registerReceiver(receiver, IntentFilter("ACTION_CUSTOM"))
// 静态注册 (AndroidManifest.xml)
<receiver android:name=".MyReceiver">
<intent-filter>
<action android:name="ACTION_BOOT_COMPLETED" />
</intent-filter>
</receiver>有序广播 vs 无序广播
| 类型 | 描述 | 特点 |
|---|---|---|
| 无序广播 | 所有接收者同时收到 | 快速、不可拦截 |
| 有序广播 | 按优先级依次传递 | 可中止传播、可修改数据 |
3.2 面试考点
Q1: 静态注册和动态注册的区别?
A:
- 静态注册: 应用未启动也能接收,AndroidManifest.xml 中注册
- 动态注册: 需要手动 unregister,应用运行期间有效
- Android 12+: 静态注册受限,大部分广播改为动态注册
Q2: 为什么推荐本地广播?
A:
- 安全性: 不跨进程,更可靠
- 性能: 避免进程间通信开销
- 注意: LocalBroadcastManager 已废弃,推荐使用 EventBus、Flow 等
Q3: 系统广播有哪些?
A:
ACTION_BOOT_COMPLETED: 系统启动完成ACTION_SHUTDOWN: 系统关机ACTION_BATTERY_LOW: 电量低ACTION_SCREEN_OFF: 屏幕关闭CONNECTIVITY_ACTION: 网络连接变化(已废弃)
四、ContentProvider(内容提供者)
4.1 基本概念
ContentProvider 是 Android 提供的在应用之间共享数据的标准接口。
4.2 核心操作
kotlin
// CRUD 操作
ContentResolver.insert(uri, values) // 插入
ContentResolver.query(uri, columns, ...) // 查询
ContentResolver.update(uri, values, ...) // 更新
ContentResolver.delete(uri, ...) // 删除4.3 面试考点
Q1: ContentProvider 的作用?
A:
- 数据共享: 在不同应用之间安全地共享数据
- 权限控制: 通过 permission 控制访问权限
- 数据抽象: 提供统一的数据访问接口
Q2: UriMatcher 的作用?
A:
- 解析 URI,匹配不同的数据路径
- 返回匹配码,用于区分不同操作
kotlin
val matcher = UriMatcher(UriMatcher.NO_MATCH)
matcher.addURI("com.example.provider", "books", BOOKS)
matcher.addURI("com.example.provider", "books/#", BOOK_ID)Q3: Cursor 的特点?
A:
- 指向数据游标,类似数据库结果集
- 需要手动
close()避免内存泄漏 - Android 推荐使用
Loader或Room自动管理
五、综合问题
Q1: Activity 和 Service 如何通信?
A:
- BroadcastReceiver: 通过广播通信
- Binder: bindService 绑定
- Messenger: 远程通信(基于 AIDL)
- LocalSocket: 本地 Socket 通信
- AIDL: 跨进程通信
- SharedPreference/数据库: 共享数据
Q2: 什么是 Intent?
A: Intent 是 Android 组件间通信的"消息包",包含:
- Action: 动作描述(如 Intent.ACTION_VIEW)
- Data: 数据 URI
- Type: 数据 MIME 类型
- Category: 分类信息
- Component: 目标组件类名
- Extras: 附加数据
Q3: 隐式 Intent 如何匹配?
A: 匹配顺序:
- Component: 指定组件,直接匹配
- Action: 匹配 IntentFilter 的 action
- Data: 匹配 data 和 mimeType
- Category: 所有 category 都要匹配
- Permission: 需要相应权限
Q4: PendingIntent 的作用?
A:
- 授权其他应用使用自己的 Intent
- 用于闹钟、通知、快捷方式等场景
- 类型:startActivity、startService、sendBroadcast
六、实战代码示例
Activity 启动示例
kotlin
// 显式启动
val intent = Intent(this, TargetActivity::class.java)
intent.putExtra("key", "value")
startActivity(intent)
// 隐式启动
val intent = Intent(Intent.ACTION_VIEW).apply {
data = Uri.parse("https://example.com")
}
startActivity(intent)
// 启动并获取结果
startActivityForResult(intent, REQUEST_CODE)
// AndroidX 推荐方式
val launcher = registerForActivityResult(StartActivityResult()) { result ->
// 处理结果
}
launcher.launch(intent)Service 启动示例
kotlin
// 启动服务
startService(Intent(this, MyService::class.java))
// 绑定服务
bindService(Intent(this, MyService::class.java), connection, Context.BIND_AUTO_CREATE)
// 前台服务
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val notification = NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Music Player")
.setContentText("Playing...")
.setSmallIcon(R.drawable.ic_music)
.build()
startForeground(1, notification)
return START_STICKY // 服务被杀后自动重启
}七、性能优化建议
Activity 启动优化
- 避免在 onCreate 中加载大量数据
- 使用
launchMode合理复用 Activity - 预加载下一个页面资源
Service 优化
- 及时
stopSelf()或stopService() - 前台服务显示必要通知
- 避免在 Service 中直接操作 UI
- 及时
Broadcast 优化
- 优先使用动态注册
- 避免注册过多广播
- 使用 sticky 广播注意内存
ContentProvider 优化
- 使用
ContentObserver监听变化 - 合理分页加载数据
- 避免在主线程操作数据库
- 使用
八、常见面试题汇总
| 问题 | 难度 | 出现频率 |
|---|---|---|
| Activity 生命周期 | ⭐⭐ | ⭐⭐⭐⭐⭐ |
| 四种启动模式 | ⭐⭐⭐ | ⭐⭐⭐⭐ |
| Service vs Thread | ⭐⭐ | ⭐⭐⭐⭐ |
| 广播注册区别 | ⭐⭐ | ⭐⭐⭐ |
| ContentProvider 作用 | ⭐⭐⭐ | ⭐⭐ |
| Intent 传递数据限制 | ⭐⭐⭐ | ⭐⭐⭐ |
📚 参考资料
🔗 下一篇: Activity 生命周期深度解析