Activity启动流程总结

1. 应用进程启动 Activity

当应用中的某个 Activity 调用 startActivity 方法时,实际上是通过 ContextImpl 类中的 startActivity 方法发起的。

java
深色版本
public class ContextImpl extends Context {
    @Override
    public void startActivity(Intent intent) {
        // 调用 Instrumentation 的 startActivity 方法
        mInstrumentation.execStartActivity(
            getOuterContext(), mMainThread.getApplicationThread(), null,
            (Activity) null, intent, -1, null);
    }
}

2. 通过 Instrumentation 发起请求

ContextImpl 会调用 Instrumentation 类中的 execStartActivity 方法来处理启动请求。

java
深色版本
public class Instrumentation {
    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread appThread = (IApplicationThread) contextThread;
        // 通过 Binder 调用 AMS(ActivityTaskManagerService)
        int result = ActivityTaskManager.getService().startActivity(
                appThread, who.getBasePackageName(), intent,
                intent.resolveTypeIfNeeded(who.getContentResolver()),
                token, target != null ? target.mEmbeddedID : null,
                requestCode, 0, null, options);
        return new ActivityResult(result, null);
    }
}

3. 跨进程通信到 ActivityTaskManagerService (ATMS)

startActivity 请求通过 Binder 机制传递给系统服务进程中的 ActivityTaskManagerService(ATMS)。ATMS 是运行在 SystemServer 进程中的一个服务,负责管理所有应用的 Activity 生命周期和任务栈。

ATMS 处理启动请求

在 ATMS 中,启动 Activity 的逻辑主要由 ActivityStarter 类处理。它会解析 Intent 并根据启动模式(如 singleTasksingleInstance 等)决定如何启动或复用 Activity

java
深色版本
public class ActivityStarter {
    public int startActivityMayWait(IApplicationThread caller, String callingPackage, Intent intent,
            String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int flags, ProfilerInfo profilerInfo, Bundle options) {
        // 解析 Intent 和启动模式
        TaskRecord task = findTaskForActivity(intent.getComponent());
        if (task != null && isSingleTaskMode(intent)) {
            // 如果任务栈已存在且是 singleTask 模式
            bringTaskToFront(task);
            return START_TASK_TO_FRONT;
        } else {
            // 创建新的任务栈并启动 Activity
            TaskRecord newTask = createNewTask(intent);
            startNewActivity(newTask, intent);
            return START_SUCCESS;
        }
    }

    private boolean isSingleTaskMode(Intent intent) {
        // 判断是否是 singleTask 模式
        return intent.getComponent().getLaunchMode() == ActivityInfo.LAUNCH_SINGLE_TASK;
    }

    private TaskRecord findTaskForActivity(ComponentName componentName) {
        // 查找包含指定 Activity 的任务栈
        for (TaskRecord task : mTaskStacks) {
            if (task.containsActivity(componentName)) {
                return task;
            }
        }
        return null;
    }

    private void bringTaskToFront(TaskRecord task) {
        // 将任务栈置于前台,并清理位于目标 Activity 之上的所有 Activity
        moveTaskToFront(task);
    }

    private void moveTaskToFront(TaskRecord task) {
        // 将任务栈置于前台
        mTaskStacks.remove(task);
        mTaskStacks.add(task); // 或者使用特定的方法将任务栈置于前台
    }

    private TaskRecord createNewTask(Intent intent) {
        // 创建新的任务栈
        TaskRecord newTask = new TaskRecord();
        // 设置任务栈属性
        return newTask;
    }

    private void startNewActivity(TaskRecord task, Intent intent) {
        // 启动新的 Activity 并将其添加到任务栈中
        ActivityRecord activityRecord = new ActivityRecord(intent);
        task.addActivity(activityRecord);
    }
}

4. 通知客户端启动 Activity

一旦 ATMS 决定了如何启动或复用 Activity,它会通过 ApplicationThread 通知客户端应用启动新的 Activity。这个过程涉及到 Binder 调用,具体是通过 IApplicationThread 接口进行的。

java
深色版本
public interface IApplicationThread {
    void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
            ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
            String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state,
            PersistableBundle persistentState, List<ResultInfo> pendingResults,
            List<ReferrerIntent> pendingNewIntents, boolean notResumed, boolean isForward,
            ProfilerInfo profilerInfo);
}

5. 客户端应用处理启动请求

在客户端应用进程中,ApplicationThread 实现了 IApplicationThread 接口,并且在收到 scheduleLaunchActivity 调用后,会将请求转发给 ActivityThreadhandleLauncherActivity 方法。

java
深色版本
public class ActivityThread {
    final ApplicationThread mAppThread = new ApplicationThread();

    private class ApplicationThread extends IApplicationThread.Stub {
        @Override
        public void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
                String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state,
                PersistableBundle persistentState, List<ResultInfo> pendingResults,
                List<ReferrerIntent> pendingNewIntents, boolean notResumed, boolean isForward,
                ProfilerInfo profilerInfo) {
            sendMessage(H.LAUNCH_ACTIVITY, new ActivityClientRecord(r, data));
        }
    }

    private void handleLauncherActivity(ActivityClientRecord r) {
        // 创建并启动 Activity
        ClientTransaction transaction = ClientTransaction.obtain(applicationThread, r.token);
        transaction.addCallback(LaunchActivityItem.obtain(r.intent, r.info,
                new Configuration(), r.compatInfo, r.referrer, r.voiceInteractor, windowIsFloating,
                r.config, r.overrideConfig, r.pendingResults, r.pendingNewIntents,
                mLastNonConfigurationInstances, r.isForward, profilerInfo));
        executeTransaction(transaction);
    }

    private void executeTransaction(ClientTransaction transaction) {
        // 执行事务,包括创建和启动 Activity
        Activity activity = performLaunchActivity(transaction.getActivityClientRecord());
        if (activity != null) {
            performResumeActivity(transaction.getActivityClientRecord());
        }
    }

    private Activity performLaunchActivity(ActivityClientRecord r) {
        // 创建 Activity 实例
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
            activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
            ...
            activity.attach(appContext, this, getInstrumentation(), r.token,
                    r.ident, app, r.intent, r.activityInfo, title, r.parent,
                    r.embeddedID, r.lastNonConfigurationInstances, config,
                    r.referrer, r.voiceInteractor);
            ...
            if (r.state != null || r.persistentState != null) {
                mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                        r.persistentState);
            }
            activity.mCalled = false;
            mInstrumentation.callActivityOnCreate(activity, r.state);
            ...
            return activity;
        } catch (Exception e) {
            ...
        }
    }
}

关键点解释

  1. 跨进程通信

    • 客户端通过 Binder 调用 ActivityTaskManagerService(ATMS)的方法来启动 Activity
    • ATMS 处理任务栈和 ActivityRecord,决定如何启动或复用 Activity
  2. 任务栈管理

    • ActivityTaskManagerService 使用 ActivityStarter 类来解析 Intent 并根据启动模式决定如何启动或复用 Activity
    • 如果需要启动新的 Activity,则将其添加到适当的任务栈中;如果需要复用现有实例,则调整任务栈以确保该实例位于栈顶。
  3. 通知客户端

    • ActivityTaskManagerService 通过 ApplicationThread 通知客户端应用启动新的 Activity
    • ApplicationThread 实现了 IApplicationThread 接口,并在收到 scheduleLaunchActivity 调用后,将请求转发给 ActivityThreadhandleLauncherActivity 方法。
  4. 启动 Activity

    • 在客户端应用进程中,ActivityThreadhandleLauncherActivity 方法负责创建并启动 Activity 实例。
    • performLaunchActivity 方法用于创建 Activity 实例,并调用其生命周期方法(如 onCreateonStart 等)。

总结

以下是经过整理后的完整流程:

  1. 应用进程启动 Activity

    • 应用中的某个 Activity 调用 startActivity 方法,实际通过 ContextImpl 类中的 startActivity 方法发起请求。
  2. 通过 Instrumentation 发起请求

    • ContextImpl 调用 Instrumentation 类中的 execStartActivity 方法来处理启动请求。
  3. 跨进程通信到 ActivityTaskManagerService (ATMS)

    • startActivity 请求通过 Binder 机制传递给系统服务进程中的 ActivityTaskManagerService(ATMS)。
    • ATMS 解析 Intent 并根据启动模式决定如何启动或复用 Activity
  4. 通知客户端启动 Activity

    • ATMS 通过 ApplicationThread 通知客户端应用启动新的 Activity
    • ApplicationThread 实现了 IApplicationThread 接口,并在收到 scheduleLaunchActivity 调用后,将请求转发给 ActivityThreadhandleLauncherActivity 方法。
  5. 客户端应用处理启动请求

    • 在客户端应用进程中,ActivityThreadhandleLauncherActivity 方法负责创建并启动 Activity 实例。
    • performLaunchActivity 方法用于创建 Activity 实例,并调用其生命周期方法(如 onCreateonStart 等)。

通过这一系列步骤,Android 系统能够高效地管理和调度 Activity 的生命周期,确保应用的正常运行。

posted @ 2025-02-05 11:42  蜗牛攀爬  阅读(160)  评论(0)    收藏  举报