深入探讨 Android 核心组件生命周期 API 的实现原理及常见问题的底层机制

231 阅读10分钟

深入剖析 Android 核心组件(ActivityFragmentServiceBroadcastReceiver)生命周期 API 背后的实现原理,以及常见问题(如屏幕旋转、进程恢复)的底层机制,并结合 Android 源码(基于 AOSP)和系统机制,详细讲解生命周期的原理。


一、Activity 生命周期的底层原理

1. Activity 生命周期的实现机制

Activity 是 Android 应用的核心组件,其生命周期由 ActivityManagerService (AMS)ActivityThread 共同管理。以下是生命周期的底层实现原理:

核心组件与流程

  • ActivityManagerService (AMS):
    • 运行在系统进程(System Server)中,负责管理所有 Activity 的生命周期、栈管理(如任务栈、进程栈)以及进程调度。
    • AMS 通过 Binder IPC 与应用进程通信,调用 Activity 的生命周期方法。
  • ActivityThread:
    • 运行在应用进程的主线程,是应用的入口点,负责接收 AMS 的指令并调度 Activity 生命周期。
    • 通过 HandlerLooper 机制处理 AMS 发送的消息(如启动、暂停 Activity)。
  • Instrumentation:
    • 是一个桥接层,负责在应用进程内调用 Activity 的具体生命周期方法(如 onCreateonPause)。
    • 提供生命周期调用的钩子,开发者可以通过自定义 Instrumentation 拦截生命周期。

生命周期调度流程

onCreate 为例,剖析其调用链:

  1. 用户启动 Activity:
    • 用户点击应用图标或通过 Intent 触发 Activity 启动。
    • 系统通过 Launcher 或其他组件生成 Intent,调用 startActivity
  2. AMS 接收请求:
    • startActivity 通过 Binder 调用 AMS 的 startActivity 方法。
    • AMS 检查权限、解析 Intent、确定目标 Activity,并决定是否创建新进程或复用现有进程。
  3. 进程创建与 ActivityThread 初始化:
    • 如果需要新进程,AMS 通过 Zygote fork 出新进程,并加载 ActivityThread
    • ActivityThreadmain 方法初始化主线程 Looper 和 Handler。
  4. Activity 实例化与生命周期调用:
    • ActivityThread 接收 AMS 的 LAUNCH_ACTIVITY 消息,通过 Instrumentation 实例化 Activity(调用 newActivity)。
    • Instrumentation 调用 Activity.performCreate -> Activity.onCreate
  5. UI 渲染:
    • onCreate 中调用 setContentView,触发 View 树的创建和布局,最终由 ViewRootImpl 完成绘制。

源码(简化,基于 AOSP Android 12):

// ActivityThread.java
public void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    Activity a = performLaunchActivity(r, customIntent); // 创建并调用 onCreate
    if (a != null) {
        handleResumeActivity(r.token, false, r.isForward, "handleLaunchActivity");
    }
}

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    Activity activity = null;
    try {
        java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
        activity = mInstrumentation.newActivity(cl, r.activityInfo.name, r.intent); // 实例化 Activity
        if (activity != null) {
            activity.attach(...); // 初始化 Context、Window 等
            mInstrumentation.callActivityOnCreate(activity, r.state); // 调用 onCreate
        }
    } catch (Exception e) {
        // 异常处理
    }
    return activity;
}

// Instrumentation.java
public void callActivityOnCreate(Activity activity, Bundle icicle) {
    activity.performCreate(icicle); // 调用 Activity 的 performCreate
}

// Activity.java
final void performCreate(Bundle icicle) {
    onCreate(icicle); // 开发者重写的 onCreate
    mActivityTransitionState.readState(icicle);
    performCreateCommon();
}

生命周期状态机

Activity 的生命周期由 AMS 维护的状态机控制,状态包括:

  • CREATEDSTARTEDRESUMEDPAUSEDSTOPPEDDESTROYED
  • AMS 通过 ActivityRecord(AMS 内部表示 Activity 的对象)跟踪每个 Activity 的状态,并根据用户操作(如按 Home 键、屏幕旋转)或系统事件(如进程杀死)触发状态转换。

屏幕旋转的底层原理

  • 触发机制:
    • 屏幕旋转导致设备配置(Configuration)变化(如 orientationscreenSize)。
    • 系统通过 WindowManagerService (WMS) 检测配置变化,通知 AMS。
    • AMS 默认销毁并重建 Activity,以加载新的资源(如横屏布局)。
  • 源码分析:
    // ActivityStackSupervisor.java (AMS)
    void handleConfigurationChanged(Configuration config) {
        for (ActivityRecord record : mActivityRecords) {
            if (!record.handlesConfigChanges()) { // 检查 android:configChanges
                record.getTask().restartActivity(record); // 重启 Activity
            }
        }
    }
    
  • 为什么销毁重建:
    • Android 假设配置变化需要重新加载资源(如布局、字符串),因此重建 Activity 是默认行为。
    • 如果开发者声明 android:configChanges,AMS 不会销毁 Activity,而是调用 onConfigurationChanged

进程恢复的底层原理

  • 进程死亡场景:
    • 系统因内存压力杀死应用进程(优先级低的进程,如后台进程)。
    • 用户重新打开应用,系统尝试恢复之前的 Activity 栈。
  • 恢复机制:
    • AMS 保存 Activity 栈状态(TaskRecordActivityRecord),包括每个 Activity 的 Bundle(通过 onSaveInstanceState 保存)。
    • 恢复时,AMS 通过 ActivityThread 重新创建进程,并根据保存的栈状态重建 Activity,调用 onCreate 并传入保存的 savedInstanceState
  • 源码分析:
    // ActivityStackSupervisor.java
    void restorePersistentTaskIfNeeded(TaskRecord task) {
        for (ActivityRecord ar : task.mActivities) {
            if (ar.state != null) {
                scheduleLaunchActivity(ar.intent, ar.state); // 恢复 Activity
            }
        }
    }
    

2. 常见问题与底层解决方案

屏幕旋转

  • 问题本质: 配置变化触发 Activity 重建,onSaveInstanceStateonCreate 之间的状态传递依赖 AMS 保存的 Bundle
  • 底层解决方案:
    1. ViewModel:
      • ViewModel 存储在 ViewModelStore 中,由 ViewModelProvider 管理。
      • 配置变化时,Activity 销毁但 ViewModelStore 保留(通过 NonConfigurationInstances),因此 ViewModel 不丢失。
      • 源码:
        // ComponentActivity.java
        Object getLastNonConfigurationInstance() {
            return mViewModelStore; // 保存 ViewModelStore
        }
        
    2. SavedStateHandle:
      • 通过 SavedStateRegistry 保存状态到 Bundle,在进程恢复时由 AMS 恢复。
      • 源码:
        // SavedStateRegistry.java
        void performRestore(Bundle savedState) {
            if (savedState != null) {
                mRestoredState = savedState.getBundle("androidx.lifecycle.BundlableSavedStateRegistry.key");
            }
        }
        
    3. 自定义配置处理:
      • 声明 android:configChanges 后,AMS 不销毁 Activity,而是通知 onConfigurationChanged
      • 开发者需手动更新资源(如重新加载布局)。

进程恢复

  • 问题本质: 进程死亡后,AMS 尝试恢复 Activity 栈,但状态依赖 onSaveInstanceState 保存的 Bundle,而 Bundle 有大小限制(通常 1MB)。
  • 底层解决方案:
    1. 持久化存储:
      • 使用 Room 数据库或 SharedPreferences 保存状态。
      • Room 使用 SQLite,数据存储在文件系统中,不受 Bundle 限制。
      • 源码(Room 插入数据):
        // RoomDatabase.java
        public void insert(T entity) {
            SQLiteDatabase db = mDatabase;
            db.beginTransaction();
            try {
                mDao.insert(entity);
                db.setTransactionSuccessful();
            } finally {
                db.endTransaction();
            }
        }
        
    2. SavedStateHandle:
      • 结合 ViewModel 和 SavedStateRegistry,确保状态在进程恢复时由 AMS 自动恢复。
    3. 最小化 Bundle 内容:
      • 仅保存必要状态(如 ID 或标志),其他数据通过数据库或网络重新加载。

3. 代码示例(深入优化)

优化屏幕旋转和进程恢复,使用 ViewModel 和 Room:

// 数据实体
@Entity(tableName = "user_data")
data class UserData(
    @PrimaryKey val id: String,
    val input: String
)

// Room DAO
@Dao
interface UserDataDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insert(data: UserData)

    @Query("SELECT * FROM user_data WHERE id = :id")
    suspend fun getById(id: String): UserData?
}

// Room Database
@Database(entities = [UserData::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDataDao(): UserDataDao
}

// ViewModel
class MainViewModel(
    private val savedStateHandle: SavedStateHandle,
    private val userDataDao: UserDataDao
) : ViewModel() {
    private val _userInput = MutableLiveData<String>()
    val userInput: LiveData<String> get() = _userInput

    init {
        viewModelScope.launch {
            val savedData = userDataDao.getById("user_1")
            val input = savedStateHandle.get<String>("user_input") ?: savedData?.input
            _userInput.value = input
        }
    }

    fun saveInput(input: String) {
        _userInput.value = input
        savedStateHandle.set("user_input", input)
        viewModelScope.launch {
            userDataDao.insert(UserData("user_1", input))
        }
    }
}

// Activity
class MainActivity : AppCompatActivity() {
    private lateinit var viewModel: MainViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val database = Room.databaseBuilder(this, AppDatabase::class.java, "app_db").build()
        viewModel = ViewModelProvider(
            this,
            SavedStateViewModelFactory(this, MainViewModel::class.java, database.userDataDao())
        ).get(MainViewModel::class.java)

        val editText = findViewById<EditText>(R.id.editText)
        viewModel.userInput.observe(this) { input ->
            editText.setText(input)
        }
        editText.addTextChangedListener(object : TextWatcher {
            override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
                viewModel.saveInput(s.toString())
            }
            // 其他方法省略
        })
    }
}

二、Fragment 生命周期的底层原理

1. Fragment 生命周期的实现机制

Fragment 是 Activity 的子模块,其生命周期由 FragmentManagerFragmentController 管理,依赖于宿主 Activity 的生命周期。

核心组件与流程

  • FragmentManager:
    • 负责管理 Fragment 的生命周期、事务(FragmentTransaction)和回退栈。
    • 通过 FragmentHostCallback 与 Activity 交互。
  • FragmentController:
    • 协调 Fragment 和 Activity 的生命周期,确保 Fragment 状态与 Activity 同步。
  • FragmentState:
    • AMS 保存 Fragment 的状态(通过 onSaveInstanceState),在进程恢复时重建 Fragment。

生命周期调度流程

onCreateView 为例:

  1. Fragment 事务提交:
    • 开发者调用 FragmentTransaction.addreplace,提交事务到 FragmentManager
    • FragmentManager 将事务加入待执行队列。
  2. 事务执行:
    • FragmentManager 调用 execPendingActions,处理事务。
    • 创建 Fragment 实例,调用 performCreate -> onCreate
    • 调用 performCreateView -> onCreateView
  3. 视图绑定:
    • onCreateView 返回的 View 被添加到 Activity 的 View 树中。

源码(简化,基于 AOSP Android 12):

// FragmentManagerImpl.java
void moveToState(Fragment f, int newState) {
    if (f.mState < newState) {
        switch (f.mState) {
            case Fragment.INITIALIZING:
                f.performAttach();
                f.performCreate(f.mSavedFragmentState);
            case Fragment.CREATED:
                if (newState > Fragment.CREATED) {
                    f.performCreateView(f.mSavedFragmentState);
                    f.performViewCreated();
                }
            // 其他状态
        }
        f.mState = newState;
    }
}

// Fragment.java
void performCreateView(Bundle savedInstanceState) {
    mView = onCreateView(mLayoutInflater, null, savedInstanceState);
    if (mView != null) {
        mView.setSaveFromParentEnabled(false);
    }
}

屏幕旋转的底层原理

  • Fragment 的重建由宿主 Activity 触发,AMS 销毁 Activity 时,FragmentManager 保存所有 Fragment 的状态(FragmentState)。
  • 恢复时,FragmentManager 根据保存的 FragmentState 重新实例化 Fragment,调用 onCreateView 等方法。
  • 源码:
    // FragmentManagerImpl.java
    public void saveAllState() {
        ArrayList<FragmentState> states = new ArrayList<>();
        for (Fragment f : mActive.values()) {
            FragmentState fs = new FragmentState(f);
            states.add(fs);
        }
        return states;
    }
    

进程恢复的底层原理

  • AMS 保存 Activity 的 Bundle,其中包含 FragmentManager 的状态(FragmentState)。
  • 恢复时,FragmentManagerBundle 恢复 Fragment 实例,重建视图和状态。

2. 常见问题与底层解决方案

屏幕旋转

  • 问题本质: Fragment 随 Activity 重建,视图和状态需重新绑定。
  • 底层解决方案:
    1. ViewModel:
      • ViewModel 存储在 Activity 或 Fragment 的 ViewModelStore,跨配置变化保留。
    2. SavedStateHandle:
      • 保存状态到 Bundle,由 FragmentManager 和 AMS 管理。
    3. View Binding 清理:
      • onDestroyView 清理视图引用,防止内存泄漏。
      • 源码:
        // Fragment.java
        void performDestroyView() {
            if (mView != null) {
                mView = null; // 清理视图
            }
            onDestroyView();
        }
        

进程恢复

  • 问题本质: Fragment 的状态依赖 Bundle,但可能丢失复杂数据。
  • 底层解决方案:
    • 使用 Room 或文件存储持久化数据。
    • 结合 SavedStateHandle 确保关键状态恢复。

3. 代码示例(深入优化)

优化 Fragment 的状态管理:

class MainFragment : Fragment() {
    private var _binding: FragmentMainBinding? = null
    private val binding get() = _binding!!
    private lateinit var viewModel: MainViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val database = Room.databaseBuilder(requireContext(), AppDatabase::class.java, "app_db").build()
        viewModel = ViewModelProvider(
            this,
            SavedStateViewModelFactory(this, MainViewModel::class.java, database.userDataDao())
        ).get(MainViewModel::class.java)
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
        _binding = FragmentMainBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        viewModel.userInput.observe(viewLifecycleOwner) { input ->
            binding.editText.setText(input)
        }
        binding.editText.addTextChangedListener(object : TextWatcher {
            override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
                viewModel.saveInput(s.toString())
            }
            // 其他方法省略
        })
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null // 清理绑定
    }
}

三、Service 生命周期的底层原理

1. Service 生命周期的实现机制

Service 用于执行后台任务,其生命周期由 AMS 和 ServiceRecord 管理。

核心组件与流程

  • AMS:
    • 管理 Service 的创建、启动、绑定和销毁。
    • 通过 ServiceRecord 跟踪 Service 状态。
  • ActivityThread:
    • 接收 AMS 的 START_SERVICEBIND_SERVICE 消息,调用 Service 的生命周期方法。
  • ContextImpl:
    • 提供 Service 的上下文环境,处理 Intent 和 Binder。

生命周期调度流程

onStartCommand 为例:

  1. 启动 Service:
    • 开发者调用 startService,通过 Binder 通知 AMS。
  2. AMS 处理:
    • AMS 创建 ServiceRecord,检查是否需要新进程。
    • 如果 Service 未运行,AMS 发送 START_SERVICE 消息到 ActivityThread
  3. Service 执行:
    • ActivityThread 调用 handleCreateService -> Service.onCreate
    • 随后调用 handleServiceArgs -> Service.onStartCommand

源码(简化,基于 AOSP Android 12):

// ActivityThread.java
private void handleCreateService(CreateServiceData data) {
    Service service = mInstrumentation.newService(data.info.name); // 实例化 Service
    service.attach(...); // 初始化 Context
    mInstrumentation.callCreateService(service); // 调用 onCreate
    mServices.put(data.token, service);
}

private void handleServiceArgs(ServiceArgsData data) {
    Service s = mServices.get(data.token);
    if (s != null) {
        s.onStartCommand(data.args, data.flags, data.startId); // 调用 onStartCommand
    }
}

屏幕旋转的底层原理

  • Service 不直接受屏幕旋转影响,因为它没有 UI。
  • 如果 Service 与 Activity 交互,Activity 重建可能导致通信中断。

进程恢复的底层 principle

  • Started Service:
    • AMS 保存 ServiceRecord,记录 onStartCommand 的 Intent。
    • 进程恢复时,AMS 根据 START_STICKYSTART_REDELIVER_INTENT 重启 Service。
  • Bound Service:
    • 绑定状态依赖客户端(通常是 Activity),进程恢复后需重新绑定。

2. 常见问题与底层解决方案

Service 被杀死后恢复

  • 问题本质: 系统杀死进程后,AMS 根据 ServiceRecord 和返回值(如 START_STICKY)决定是否重启。
  • 底层解决方案:
    1. Foreground Service:
      • 调用 startForeground 将 Service 优先级提升为前台,降低被杀死概率。
      • 源码:
        // Service.java
        public void startForeground(int id, Notification notification) {
            mActivityManagerService.notifyForegroundService(...);
        }
        
    2. WorkManager:
      • 对于非持续任务,使用 WorkManager 替代 Service,依赖系统调度。
      • WorkManager 使用 JobScheduler 确保任务可靠执行。

内存泄漏

  • 问题本质: Bound Service 未解绑,导致 Activity 引用未释放。
  • 底层解决方案:
    • onUnbind 或 Activity 的 onStop 清理绑定。
    • 使用弱引用管理 Service 引用。

3. 代码示例(深入优化)

优化 Service 的可靠性:

class MyService : Service() {
    private val executor = Executors.newSingleThreadExecutor()

    override fun onCreate() {
        super.onCreate()
        val notification = NotificationCompat.Builder(this, "channel_id")
            .setContentTitle("Service Running")
            .setSmallIcon(R.drawable.ic_notification)
            .build()
        startForeground(1, notification)
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        intent?.getStringExtra("data")?.let { data ->
            executor.execute {
                // 执行后台任务
                Log.d("MyService", "Processing: $data")
            }
        }
        return START_STICKY
    }

    override fun onDestroy() {
        super.onDestroy()
        executor.shutdown()
    }

    override fun onBind(intent: Intent?): IBinder? = null
}

四、BroadcastReceiver 生命周期的底层原理

1. BroadcastReceiver 生命周期的实现机制

BroadcastReceiver 用于接收广播,其生命周期由 AMS 和 BroadcastQueue 管理。

核心组件与流程

  • AMS:
    • 维护广播队列(BroadcastQueue),包括普通广播和有序广播。
    • 根据 IntentFilter 匹配接收器,调度 onReceive
  • ActivityThread:
    • 动态注册的 Receiver 通过 LoadedApk 管理,AMS 将广播发送到应用进程。
  • ContextImpl:
    • 提供 Receiver 的上下文环境。

生命周期调度流程

  1. 广播发送:
    • 开发者调用 sendBroadcast,AMS 接收 Intent。
    • AMS 根据 IntentFilter 查找匹配的 Receiver(静态或动态)。
  2. 广播分发:
    • AMS 将广播加入 BroadcastQueue,按优先级分发。
    • 对于动态 Receiver,AMS 通过 Binder 调用 ActivityThreadscheduleReceiver
  3. Receiver 执行:
    • ActivityThread 调用 Receiver.onReceive

源码(简化,基于 AOSP Android 12):

// ActivityThread.java
public void scheduleReceiver(Intent intent, ActivityInfo info, int resultCode) {
    BroadcastReceiver receiver = mInstrumentation.newBroadcastReceiver(info.name); // 实例化 Receiver
    receiver.onReceive(mAppContext, intent); // 调用 onReceive
}

屏幕旋转的底层原理

  • BroadcastReceiver 不直接受屏幕旋转影响。
  • 如果 Receiver 与 Activity 交互,需注意 Activity 重建导致的通信问题。

进程恢复的底层原理

  • 静态 Receiver:
    • 由 AMS 直接管理,进程恢复时自动重新注册。
  • 动态 Receiver:
    • 依赖 Activity 或 Service,进程恢复后需重新注册。

2. 常见问题与底层解决方案

内存泄漏

  • 问题本质: 动态 Receiver 未注销,导致 Activity 引用未释放。
  • 底层解决方案:
    • unregisterReceiver 清理注册。
    • 源码:
      // ContextImpl.java
      public void unregisterReceiver(BroadcastReceiver receiver) {
          mPackageInfo.forgetReceiverDispatcher(receiver); // 移除 Receiver
      }
      

耗时操作

  • 问题本质: onReceive 执行时间受限(<10秒),否则可能触发 ANR。
  • 底层解决方案:
    • 使用 WorkManager 或 Service 处理耗时任务。
    • WorkManager 通过 JobScheduler 调度任务,确保可靠性。

3. 代码示例(深入优化)

优化 BroadcastReceiver 的任务处理:

class MyBroadcastReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent?) {
        if (intent?.action == Intent.ACTION_BOOT_COMPLETED) {
            val workRequest = OneTimeWorkRequestBuilder<MyWorker>()
                .setInputData(workDataOf("key" to "boot"))
                .build()
            WorkManager.getInstance(context).enqueue(workRequest)
        }
    }
}

class MyWorker(context: Context, params: WorkerParameters) : Worker(context, params) {
    override fun doWork(): Result {
        val key = inputData.getString("key")
        Log.d("MyWorker", "Processing: $key")
        // 执行耗时任务
        return Result.success()
    }
}

五、综合最佳实践与底层优化

  1. 状态管理:

    • 使用 ViewModel 和 SavedStateHandle 管理 Activity/Fragment 状态,结合 Room 持久化数据。
    • 最小化 Bundle 内容,复杂数据存储到数据库。
  2. 配置变化:

    • 优先使用 ViewModel 避免重建,必要时声明 android:configChanges 手动处理。
    • 确保资源(如布局、字符串)动态加载。
  3. 进程恢复:

    • 结合 AMS 的状态保存机制,使用 SavedStateRegistry 和持久化存储。
    • 测试进程死亡场景,确保状态一致。
  4. 资源清理:

    • onDestroyView(Fragment)、onUnbind(Service)、unregisterReceiver(BroadcastReceiver)清理引用。
    • 使用弱引用或 LifecycleObserver 管理资源。
  5. 后台任务:

    • Service 使用 Foreground Service 或 WorkManager 确保可靠性。
    • BroadcastReceiver 避免耗时操作,交给 WorkManager。

六、总结

通过深入剖析 ActivityFragmentServiceBroadcastReceiver 的生命周期底层原理,我们从 AMS、ActivityThread、FragmentManager 等核心组件的源码角度理解了生命周期的调度机制。屏幕旋转和进程恢复的本质在于 AMS 的状态机和 Bundle 管理,解决这些问题需要结合 ViewModel、SavedStateHandle 和持久化存储。