本章深入剖析 Android 系统的整体架构、四大组件、生命周期机制、Intent 通信体系和进程模型,是所有 Android 开发的基础与根基。
📋 章节目录
| 节 | 主题 |
|---|---|
| 1.1 | Android 系统架构分层 |
| 1.2 | 四大组件详解 |
| 1.3 | Activity 与 Fragment 完整生命周期 |
| 1.4 | Intent 机制与组件通信 |
| 1.5 | Application 类与进程模型 |
| 1.6 | AndroidManifest 深度解析 |
1.1 Android 系统架构分层
系统分层全景
┌─────────────────────────────────────────────┐
│ Applications(应用层) │
│ Phone / Settings / Camera / 你的 App │
├─────────────────────────────────────────────┤
│ Application Framework(框架层) │
│ Activity Manager / Window Manager / │
│ Content Providers / View System / │
│ Package Manager / Notification Manager │
├─────────────────────────────────────────────┤
│ Libraries + ART(运行时层) │
│ SQLite / WebKit / OpenGL ES / Media / │
│ ART(Android Runtime)/ Bionic libc │
├─────────────────────────────────────────────┤
│ HAL(硬件抽象层) │
│ Camera HAL / Audio HAL / Bluetooth HAL │
├─────────────────────────────────────────────┤
│ Linux Kernel(内核层) │
│ 驱动 / 内存管理 / 进程管理 / 安全 / 电源管理 │
└─────────────────────────────────────────────┘
ART vs Dalvik
| 特性 | Dalvik (Android < 5.0) | ART (Android 5.0+) |
|---|---|---|
| 编译方式 | JIT(运行时即时编译) | AOT + JIT + PGO |
| 启动速度 | 快(无需预编译) | 安装时预编译,启动更快 |
| 运行性能 | 较低 | 大幅提升 |
| 存储占用 | 低 | 略高(存储 OAT 文件) |
| GC | Stop-The-World | 并发、分代 GC |
Zygote 进程启动流程
init 进程
└─ Zygote(Java 世界的起点)
├─ 预加载 Android Framework 类
├─ 预加载常用资源(Drawable、Theme)
└─ 等待 fork 请求
├─ system_server(系统服务进程)
│ ├─ ActivityManagerService
│ ├─ WindowManagerService
│ └─ PackageManagerService
└─ App 进程(每个 App fork 自 Zygote)
为什么要 fork Zygote?
- 写时复制(Copy-on-Write):所有 App 共享 Zygote 已加载的内存页
- 减少每个 App 的启动时间和内存占用
1.2 四大组件详解
Activity
应用的 UI 容器,每个界面对应一个 Activity。
kotlin
// Demo: 基础 Activity
class MainActivity : AppCompatActivity() {
// ViewBinding 推荐方式
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 使用 ViewBinding 替代 findViewById
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
// 恢复状态
savedInstanceState?.let {
val count = it.getInt("count", 0)
binding.tvCount.text = count.toString()
}
binding.btnIncrement.setOnClickListener {
val current = binding.tvCount.text.toString().toInt()
binding.tvCount.text = (current + 1).toString()
}
}
// 保存状态(系统回收时)
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putInt("count", binding.tvCount.text.toString().toInt())
}
}
Service
在后台执行长时间运行任务的组件,无 UI 界面。
kotlin
// 前台 Service(用户可见)
class MusicPlayerService : Service() {
private val binder = MusicBinder()
private var isPlaying = false
inner class MusicBinder : Binder() {
fun getService(): MusicPlayerService = this@MusicPlayerService
}
override fun onBind(intent: Intent): IBinder = binder
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
when (intent?.action) {
ACTION_PLAY -> startPlaying()
ACTION_PAUSE -> pausePlaying()
ACTION_STOP -> stopSelf()
}
return START_STICKY // 系统杀死后自动重启
}
private fun startPlaying() {
isPlaying = true
// 创建前台通知(必须,否则 Android 8+ 会被杀死)
val notification = buildNotification()
startForeground(NOTIFICATION_ID, notification)
}
private fun buildNotification(): Notification {
val channelId = "music_player"
return NotificationCompat.Builder(this, channelId)
.setContentTitle("正在播放")
.setContentText("My Favorite Song")
.setSmallIcon(R.drawable.ic_music)
.setPriority(NotificationCompat.PRIORITY_LOW)
.build()
}
private fun pausePlaying() {
isPlaying = false
}
override fun onDestroy() {
super.onDestroy()
stopForeground(STOP_FOREGROUND_REMOVE)
}
companion object {
const val ACTION_PLAY = "ACTION_PLAY"
const val ACTION_PAUSE = "ACTION_PAUSE"
const val ACTION_STOP = "ACTION_STOP"
const val NOTIFICATION_ID = 1001
}
}
BroadcastReceiver
监听系统或 App 广播事件的组件。
kotlin
// 静态注册(AndroidManifest,适合接收系统广播)
class BootReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == Intent.ACTION_BOOT_COMPLETED) {
// 开机完成,启动服务
context.startForegroundService(
Intent(context, MusicPlayerService::class.java)
)
}
}
}
// 动态注册(代码中注册,随 Activity 生命周期)
class NetworkActivity : AppCompatActivity() {
private val networkReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val isConnected = checkNetworkConnectivity(context)
updateNetworkUI(isConnected)
}
}
override fun onResume() {
super.onResume()
val filter = IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)
registerReceiver(networkReceiver, filter)
}
override fun onPause() {
super.onPause()
unregisterReceiver(networkReceiver) // 必须注销,否则内存泄漏
}
// 推荐使用 LocalBroadcastManager 进行应用内通信
private fun sendLocalBroadcast() {
val intent = Intent("com.example.CUSTOM_ACTION")
intent.putExtra("data", "Hello Local Broadcast")
LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
}
private fun checkNetworkConnectivity(context: Context): Boolean {
val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
return cm.activeNetworkInfo?.isConnected == true
}
private fun updateNetworkUI(connected: Boolean) {
// 更新 UI
}
}
ContentProvider
用于跨进程共享数据,提供统一的数据访问接口。
kotlin
// 自定义 ContentProvider
class UserContentProvider : ContentProvider() {
private lateinit var database: UserDatabase
companion object {
const val AUTHORITY = "com.example.provider"
val USERS_URI: Uri = Uri.parse("content://$AUTHORITY/users")
private val uriMatcher = UriMatcher(UriMatcher.NO_MATCH).apply {
addURI(AUTHORITY, "users", 1) // 全部用户
addURI(AUTHORITY, "users/#", 2) // 单个用户
}
}
override fun onCreate(): Boolean {
database = UserDatabase.getInstance(context!!)
return true
}
override fun query(
uri: Uri, projection: Array<String>?, selection: String?,
selectionArgs: Array<String>?, sortOrder: String?
): Cursor? {
return when (uriMatcher.match(uri)) {
1 -> database.userDao().getAllCursor()
2 -> {
val userId = ContentUris.parseId(uri)
database.userDao().getUserByIdCursor(userId)
}
else -> throw IllegalArgumentException("Unknown URI: $uri")
}
}
override fun insert(uri: Uri, values: ContentValues?): Uri? {
val id = database.userDao().insert(values!!.toUser())
context?.contentResolver?.notifyChange(uri, null)
return ContentUris.withAppendedId(USERS_URI, id)
}
override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array<String>?): Int = 0
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int = 0
override fun getType(uri: Uri): String? = null
}
1.3 Activity 与 Fragment 完整生命周期
Activity 生命周期
用户打开 App
↓
onCreate() ← 初始化(只执行一次)
↓
onStart() ← 可见(不可交互)
↓
onResume() ← 可见且可交互(前台)
↓
┌── 用户按 Home / 跳转其他 App
│ ↓
│ onPause() ← 失去焦点(仍可见)
│ ↓
│ onStop() ← 不可见
│ ↓
│ onRestart() ─────────────┐
│ ↑ │ 返回
└─────────┘ 返回此 Activity
↓
onDestroy() ← 销毁
kotlin
class LifecycleDemo : AppCompatActivity() {
private val TAG = "LifecycleDemo"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d(TAG, "onCreate: isRecreated=${savedInstanceState != null}")
// 适合做:初始化 ViewModel、绑定 View、设置点击事件
}
override fun onStart() {
super.onStart()
Log.d(TAG, "onStart")
// 适合做:注册 BroadcastReceiver(某些场景)
}
override fun onResume() {
super.onResume()
Log.d(TAG, "onResume")
// 适合做:开始动画、恢复传感器、视频播放
}
override fun onPause() {
super.onPause()
Log.d(TAG, "onPause")
// 适合做:暂停动画、释放摄像头(注意:方法要快,不能做耗时操作)
}
override fun onStop() {
super.onStop()
Log.d(TAG, "onStop")
// 适合做:保存数据草稿、注销 BroadcastReceiver
}
override fun onRestart() {
super.onRestart()
Log.d(TAG, "onRestart")
}
override fun onDestroy() {
super.onDestroy()
Log.d(TAG, "onDestroy")
// 适合做:释放所有资源
}
}
Fragment 生命周期(与 Activity 对比)
Activity.onCreate()
↓
Fragment.onAttach() ← Fragment 附加到 Activity
Fragment.onCreate() ← 初始化(无 View)
Fragment.onCreateView() ← 创建并返回 View
Fragment.onViewCreated() ← View 已创建,适合初始化 UI ✅
Fragment.onStart()
Fragment.onResume()
↓ ... 运行中 ...
Fragment.onPause()
Fragment.onStop()
Fragment.onDestroyView() ← View 被销毁(Fragment 可能仍存活)
Fragment.onDestroy()
Fragment.onDetach()
kotlin
class UserProfileFragment : Fragment(R.layout.fragment_user_profile) {
// 注意:使用 viewLifecycleOwner 而非 this,避免内存泄漏
private val viewModel: UserViewModel by viewModels()
private var _binding: FragmentUserProfileBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentUserProfileBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// ✅ 使用 viewLifecycleOwner 观察 LiveData(不是 this)
viewModel.user.observe(viewLifecycleOwner) { user ->
binding.tvName.text = user.name
binding.tvEmail.text = user.email
}
// ✅ 在 lifecycleScope 中启动协程
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.uiState.collect { state ->
updateUI(state)
}
}
}
}
private fun updateUI(state: UserUiState) {
when (state) {
is UserUiState.Loading -> binding.progressBar.isVisible = true
is UserUiState.Success -> {
binding.progressBar.isVisible = false
binding.tvName.text = state.user.name
}
is UserUiState.Error -> {
binding.progressBar.isVisible = false
Snackbar.make(binding.root, state.message, Snackbar.LENGTH_LONG).show()
}
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null // ✅ 必须清空,防止内存泄漏
}
}
Activity 启动模式(LaunchMode)
| 模式 | 说明 | 典型场景 |
|---|---|---|
standard |
每次都新建实例 | 普通页面 |
singleTop |
栈顶复用(调用 onNewIntent) |
通知点击 |
singleTask |
栈中唯一实例 | 主页 / 登录页 |
singleInstance |
独立任务栈 | 来电界面 |
kotlin
// singleTop:处理通知重复点击
class NotificationActivity : AppCompatActivity() {
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
setIntent(intent)
// 处理新 Intent,而不创建新实例
val notifId = intent.getIntExtra("notif_id", -1)
loadNotification(notifId)
}
private fun loadNotification(id: Int) { /* ... */ }
}
1.4 Intent 机制与组件通信
显式 Intent vs 隐式 Intent
kotlin
// ✅ 显式 Intent(明确指定目标组件)
val explicitIntent = Intent(this, DetailActivity::class.java).apply {
putExtra("product_id", 1001)
putExtra("product_name", "Android 深度指南")
}
startActivity(explicitIntent)
// ✅ 隐式 Intent(通过 Action/Category/Data 匹配)
val implicitIntent = Intent(Intent.ACTION_VIEW).apply {
data = Uri.parse("https://www.example.com")
}
// 先检查是否有应用能处理
if (implicitIntent.resolveActivity(packageManager) != null) {
startActivity(implicitIntent)
}
// 拨打电话
val callIntent = Intent(Intent.ACTION_DIAL, Uri.parse("tel:10086"))
startActivity(callIntent)
// 分享文本
val shareIntent = Intent.createChooser(
Intent(Intent.ACTION_SEND).apply {
type = "text/plain"
putExtra(Intent.EXTRA_TEXT, "分享这段文字")
},
"分享到"
)
startActivity(shareIntent)
ActivityResultLauncher(现代方式替代 onActivityResult)
kotlin
class CameraActivity : AppCompatActivity() {
// ✅ 现代方式:ActivityResultLauncher
private val takePictureLauncher = registerForActivityResult(
ActivityResultContracts.TakePicturePreview()
) { bitmap ->
bitmap?.let {
binding.ivPhoto.setImageBitmap(it)
}
}
private val pickImageLauncher = registerForActivityResult(
ActivityResultContracts.GetContent()
) { uri ->
uri?.let {
binding.ivPhoto.setImageURI(it)
}
}
// 自定义 Contract
private val loginLauncher = registerForActivityResult(
object : ActivityResultContract<Unit, Boolean>() {
override fun createIntent(context: Context, input: Unit) =
Intent(context, LoginActivity::class.java)
override fun parseResult(resultCode: Int, intent: Intent?) =
resultCode == RESULT_OK
}
) { isLoggedIn ->
if (isLoggedIn) {
loadUserData()
}
}
private fun loadUserData() { /* ... */ }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityCameraBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.btnCamera.setOnClickListener {
takePictureLauncher.launch(null)
}
binding.btnGallery.setOnClickListener {
pickImageLauncher.launch("image/*")
}
}
private lateinit var binding: ActivityCameraBinding
}
进程间通信(AIDL)
kotlin
// IRemoteService.aidl
interface IRemoteService {
int getPid();
String getAppName();
void registerCallback(IRemoteCallback callback);
}
// 服务端实现
class RemoteService : Service() {
private val binder = object : IRemoteService.Stub() {
override fun getPid(): Int = Process.myPid()
override fun getAppName(): String = "Remote Service App"
override fun registerCallback(callback: IRemoteCallback?) {
// 注册回调(Binder 传递)
}
}
override fun onBind(intent: Intent): IBinder = binder
}
// 客户端连接
class ClientActivity : AppCompatActivity() {
private var remoteService: IRemoteService? = null
private val serviceConnection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName, service: IBinder) {
remoteService = IRemoteService.Stub.asInterface(service)
Log.d("Client", "Service PID: ${remoteService?.pid}")
}
override fun onServiceDisconnected(name: ComponentName) {
remoteService = null
}
}
override fun onStart() {
super.onStart()
val intent = Intent().apply {
component = ComponentName("com.example.server", "com.example.server.RemoteService")
}
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
}
override fun onStop() {
super.onStop()
unbindService(serviceConnection)
}
}
1.5 Application 类与进程模型
自定义 Application
kotlin
// MyApplication.kt
@HiltAndroidApp // 使用 Hilt 时必须加此注解
class MyApplication : Application() {
// 进程名(多进程时有多个 Application 实例)
private val processName: String by lazy {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
getProcessName()
} else {
getCurrentProcessNameLegacy()
}
}
override fun onCreate() {
super.onCreate()
// 只在主进程初始化
if (isMainProcess()) {
initMainProcessComponents()
}
// 所有进程都初始化
initCommonComponents()
}
private fun isMainProcess(): Boolean =
processName == packageName
private fun initMainProcessComponents() {
// 初始化崩溃监控
initCrashReporter()
// 初始化日志(主进程)
initLogger()
}
private fun initCommonComponents() {
// 初始化图片加载器等
}
private fun initCrashReporter() {
Thread.setDefaultUncaughtExceptionHandler { thread, throwable ->
// 全局异常捕获
Log.e("Crash", "Uncaught exception in thread ${thread.name}", throwable)
// 写入崩溃日志
saveCrashLog(throwable)
// 重启 App 或退出
exitProcess(1)
}
}
private fun initLogger() {
if (BuildConfig.DEBUG) {
Timber.plant(Timber.DebugTree())
} else {
Timber.plant(CrashlyticsTree()) // 生产环境上报
}
}
private fun saveCrashLog(throwable: Throwable) { /* ... */ }
private fun getCurrentProcessNameLegacy(): String = ""
}
Android 进程模型
进程优先级(从高到低,越低越容易被系统回收):
1. 前台进程 ← 正在与用户交互的 Activity
2. 可见进程 ← 有 Activity 可见但不在前台
3. 服务进程 ← 运行 Service(如音乐播放)
4. 缓存进程 ← 按返回键退出的 App
kotlin
// 防止低内存被杀:使用 onTrimMemory 释放缓存
class MyApplication : Application() {
override fun onTrimMemory(level: Int) {
super.onTrimMemory(level)
when (level) {
TRIM_MEMORY_UI_HIDDEN -> {
// App 进入后台,释放 UI 相关缓存
ImageCache.clearMemoryCache()
}
TRIM_MEMORY_RUNNING_LOW,
TRIM_MEMORY_RUNNING_CRITICAL -> {
// 内存紧张,释放所有缓存
ImageCache.clearAllCache()
DatabaseCache.clear()
}
}
}
}
ANR(Application Not Responding)
kotlin
// ANR 触发条件
// - 主线程被阻塞 > 5秒(Activity/BroadcastReceiver)
// - BroadcastReceiver 超过 10 秒
// - Service 超过 20 秒
// ❌ 错误:在主线程做网络请求
class BadActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 这会导致 ANR!
val result = URL("https://api.example.com/data").readText()
}
}
// ✅ 正确:使用协程在 IO 线程执行
class GoodActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycleScope.launch {
val result = withContext(Dispatchers.IO) {
URL("https://api.example.com/data").readText()
}
// 回到主线程更新 UI
binding.tvResult.text = result
}
}
private lateinit var binding: ActivityGoodBinding
}
1.6 AndroidManifest 深度解析
xml
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.myapp">
<!-- 权限声明 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.CAMERA" />
<!-- READ_EXTERNAL_STORAGE 在 Android 13+ 被粒度权限替代 -->
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
<!-- Android 13+ 精细媒体权限 -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<!-- 硬件特性声明 -->
<uses-feature
android:name="android.hardware.camera"
android:required="false" /> <!-- required=false:没有相机的设备也可安装 -->
<application
android:name=".MyApplication"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MyApp"
android:networkSecurityConfig="@xml/network_security_config"
tools:targetApi="31">
<!-- 主 Activity -->
<activity
android:name=".ui.main.MainActivity"
android:exported="true"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<!-- Deep Link 支持 -->
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="https"
android:host="www.example.com"
android:pathPrefix="/product/" />
</intent-filter>
</activity>
<!-- 详情 Activity(不需要被外部调用,exported=false)-->
<activity
android:name=".ui.detail.DetailActivity"
android:exported="false"
android:parentActivityName=".ui.main.MainActivity" /> <!-- 支持返回按钮 -->
<!-- Service -->
<service
android:name=".service.MusicPlayerService"
android:exported="false"
android:foregroundServiceType="mediaPlayback" />
<!-- BroadcastReceiver(静态注册) -->
<receiver
android:name=".receiver.BootReceiver"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<!-- ContentProvider -->
<provider
android:name=".provider.UserContentProvider"
android:authorities="com.example.myapp.provider"
android:exported="false"
android:grantUriPermissions="true" />
<!-- FileProvider(用于分享文件)-->
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>
</manifest>
xml
<!-- res/xml/network_security_config.xml -->
<!-- 配置网络安全(防止明文传输)-->
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="false">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
<!-- 开发环境允许本地明文 -->
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">10.0.2.2</domain>
<domain includeSubdomains="true">localhost</domain>
</domain-config>
</network-security-config>
Demo 代码:chapter01
kotlin
// chapter01/SystemArchDemo.kt
package com.example.androiddemos.chapter01
import android.app.Activity
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.Bundle
import android.os.IBinder
import android.util.Log
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class Chapter01DemoActivity : AppCompatActivity() {
private val TAG = "Chapter01"
// ---- ActivityResultLauncher ----
private val requestPermissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { permissions ->
permissions.forEach { (permission, granted) ->
Log.d(TAG, "$permission: ${if (granted) "已授权" else "拒绝"}")
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 演示协程字典
demonstrateCoroutineDispatcher()
// 演示权限请求
requestPermissionLauncher.launch(
arrayOf(
android.Manifest.permission.CAMERA,
android.Manifest.permission.ACCESS_FINE_LOCATION
)
)
}
private fun demonstrateCoroutineDispatcher() {
lifecycleScope.launch {
Log.d(TAG, "主线程: ${Thread.currentThread().name}")
val result = withContext(Dispatchers.IO) {
Log.d(TAG, "IO线程: ${Thread.currentThread().name}")
// 模拟耗时操作
Thread.sleep(100)
"任务完成"
}
Log.d(TAG, "回到主线程: $result, 线程: ${Thread.currentThread().name}")
}
}
/**
* 演示进程生命周期各回调时机
*/
override fun onLowMemory() {
super.onLowMemory()
Log.w(TAG, "系统内存极低!释放所有缓存")
}
override fun onTrimMemory(level: Int) {
super.onTrimMemory(level)
Log.d(TAG, "onTrimMemory level=$level")
}
}
章节总结
| 知识点 | 必掌握程度 | 面试频率 |
|---|---|---|
| Android 分层架构 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 四大组件及使用场景 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| Activity 生命周期 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| Fragment 生命周期 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
| Intent(显式/隐式) | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
| ActivityResultLauncher | ⭐⭐⭐⭐ | ⭐⭐⭐ |
| Activity 启动模式 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| Zygote 启动流程 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
| ANR 原因与避免 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| AndroidManifest 配置 | ⭐⭐⭐⭐ | ⭐⭐⭐ |