Android进阶知识(二十七):Activity的启动过程

Android进阶知识(二十七):Activity的启动过程

  Activity组件的主要作用是展示一个界面并和用户交互,其扮演的是一个前台界面的角色。关于Activity启动的触发(Intent)以及相关的启动模式等,笔者在Android基础知识(五):Activity的生命周期Android基础知识(六):Activity的启动模式Android基础知识(七):Activity互调之间的生命周期变化与onNewIntent()触发机制以及Android进阶知识(二):Activity启动模式进阶之多任务栈与Flags中做了介绍。
  这一篇笔者将对Activity的启动过程的流程进行总结,并提及一些需要注意的点,这里笔者不会铺太多源码(毕竟太多了)。

一、ActivityTaskManagerService(ATMS)

  Google将Android的版本更新到10.0版本(SDK 29)之后,Activity的启动流程相比之前发生了些许变化,其中最大的变化就是用来管理Activity的ActivityManagerService(AMS),变更为ActivityTaskManagerService(ATMS)
  为了兼容,原本的AMS代码也都委托给ATMS中进行处理。

public int startActivity(IApplicationThread caller, String callingPackage,
        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
        int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
    return mActivityTaskManager.startActivity(caller, callingPackage, intent, resolvedType,
            resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions);
}

  这就严重导致了基于Android 5.0版本的《Android开发艺术探索》内的启动流程不适用,不过也无需担心,即使流程变动,其基本思想是不会改变的。

二、Activity的启动过程

  Activity的启动过程流程图如下所示。
在这里插入图片描述
  其中黑色虚线是指过程经过多个重载方法,最终调用箭头指向的方法。紫色虚线指该过程调用为远程服务调用,即IPC过程。
在这里插入图片描述
  上面的流程图是方法具体调用的流程(其实也是忽略了许多重载方法调用),简单起见,Activity启动过程的流程可以用如下表示。
在这里插入图片描述

三、ApplicationThread

ApplicationThread是ActivityThread的内部类,继承自IApplicationThread.Stub即Binder

private class ApplicationThread extends IApplicationThread.Stub {
    // ...
    @Override
    public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
        ActivityThread.this.scheduleTransaction(transaction);
    }
    // ...
}

  因此在Activity启动流程中,ATMS回调ApplicationThread的方法,该方法在Binder线程池中的线程执行,这也是为什么需要使用Handler来切换线程到ActivityThread所在线程的原因
在这里插入图片描述

四、onPause与onResume的执行时机

  在流程中,我们可以知道Activity的启动过程在ActivityStack的resumeTopActivityInnerLocked方法中,其会调用startPausingLocked方法,从而回调ApplicationThread,接着线程切换调用ActivityThread的handlePauseActivity方法,以执行回调onPause。
  这也就是在基础知识阶段中,提到的在启动新Activity时候,旧的Activity的onPause方法回调在新Activity的onCreate方法回调之前执行的原因
在这里插入图片描述
  那么另一个问题来了,Activity的启动过程是开发者通过代码触发的,同理通过调用finish方法也可以触发Activity的结束过程(流程基本类似),那么其他方法像onResume是如何被调用的呢?
在这里插入图片描述
  在《Android开发艺术探索》以及很多博客上说的是,ActivityThread的handleLaunchActivity中调用了handleResumeActivity,从而调用了onResume。但是事实上,在Android 10.0的源码完全不是怎么一回事。这导致了笔者大脑当机了半天。
在这里插入图片描述
  那么到底是怎么调用的呢?笔者通过阅读源码,终于找到了源头。在realStartActivityLocked中有这样一段代码。

boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
        boolean andResume, boolean checkConfig) throws RemoteException {
    // ...
    if (andResume) {
        lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward());
    } else {
        lifecycleItem = PauseActivityItem.obtain();
    }
    clientTransaction.setLifecycleStateRequest(lifecycleItem);

    // Schedule transaction.
    mService.getLifecycleManager().scheduleTransaction(clientTransaction);
    // ...            
}

  根据上面的流程我们知道clientTransaction最终会被TransactionExecutor的execute使用,而这里调用的clientTransaction.setLifecyclesStateRequest表示设置客户端,即Application在执行事务后应该处于的生命周期状态。由于是启动Activity,因此这里的lifecycleItem为ResumeActivityItem,也就是Application应该处于resume状态。
  再来看看execute的部分代码,在上面的流程中execute调用了executeCallbacks方法之外,还调用了另一个方法executeLifecycleState

public void execute(ClientTransaction transaction) {
    // ...
    executeCallbacks(transaction);

    executeLifecycleState(transaction);
    mPendingActions.clear();
    if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "End resolving transaction");
}

private void executeLifecycleState(ClientTransaction transaction) {
    final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
    if (lifecycleItem == null) {
        // No lifecycle request, return early.
        return;
    }

    // ...
    
    // Execute the final transition with proper parameters.
    lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
    lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
}

  我想读者也明白了executeLifecycleState就是取出前面设置了lifecycleItem进而调用对应的execute方法,最终就可以回调到onResume。这里总结一些流程如下,这里省略了部分流程以及executeCallback的流程。
在这里插入图片描述
  值得一提的是,与onCreate的调用不同,performResumeActivity是调用的Activity的performResume方法,接着调用Instrumentation的callActivityOnResume,进而调用Activity的onResume方法。

五、performLaunchActivity的工作

  在前面的流程中,笔者只是把performLaunchActivity最重要的工作调用Instrumentation的callActivityOnCreate方法,从而调用onCreate方法,画入了流程中,但是实际上performLaunchActivity的工作主要有五件事

  1. 从ActivityClientRecord中获取待启动的Activity的组件信息
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
    r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
            Context.CONTEXT_INCLUDE_CODE);
}

ComponentName component = r.intent.getComponent();
if (component == null) {
    component = r.intent.resolveActivity(
        mInitialApplication.getPackageManager());
    r.intent.setComponent(component);
}

if (r.activityInfo.targetActivity != null) {
    component = new ComponentName(r.activityInfo.packageName,
            r.activityInfo.targetActivity);
}
  1. 通过Instrumentation的newActivity方法使用类加载器创建Activity对象
Activity activity = null;
try {
    java.lang.ClassLoader cl = appContext.getClassLoader();
    activity = mInstrumentation.newActivity(
            cl, component.getClassName(), r.intent);
    StrictMode.incrementExpectedActivityCount(activity.getClass());
    r.intent.setExtrasClassLoader(cl);
    r.intent.prepareToEnterProcess();
    if (r.state != null) {
        r.state.setClassLoader(cl);
    }
} catch (Exception e) {
    if (!mInstrumentation.onException(activity, e)) {
        throw new RuntimeException(
            "Unable to instantiate activity " + component
            + ": " + e.toString(), e);
    }
}
  1. 通过LoadedApk的makeApplication方法尝试创建Application对象
public Application makeApplication(boolean forceDefaultAppClass,
        Instrumentation instrumentation) {
    if (mApplication != null) {
        return mApplication;
    }

    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");

    Application app = null;
    String appClass = mApplicationInfo.className;
    if (forceDefaultAppClass || (appClass == null)) {
        appClass = "android.app.Application";
    }

    try {
        java.lang.ClassLoader cl = getClassLoader();
        if (!mPackageName.equals("android")) {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                    "initializeJavaContextClassLoader");
            initializeJavaContextClassLoader();
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        }
        ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
        app = mActivityThread.mInstrumentation.newApplication(
                cl, appClass, appContext);
        appContext.setOuterContext(app);
    } catch (Exception e) {
        if (!mActivityThread.mInstrumentation.onException(app, e)) {
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            throw new RuntimeException(
                "Unable to instantiate application " + appClass
                + ": " + e.toString(), e);
        }
    }
    mActivityThread.mAllApplications.add(app);
    mApplication = app;

    if (instrumentation != null) {
        try {
            instrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
            if (!instrumentation.onException(app, e)) {
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                throw new RuntimeException(
                    "Unable to create application " + app.getClass().getName()
                    + ": " + e.toString(), e);
            }
        }
    }
    // ...

    return app;
}

  从makeApplication的实现可以看出,如果Application已经被创建,那么不会再重复创建,这也就意味着一个应用只有一个Application对象
在这里插入图片描述
  另外Application创建完毕之后,系统会通过Instrumentation的callApplicationOnCreate来调用Application的onCreate方法

  1. 创建ContextImpl对象并通过Activity的attach方法完成重要数据初始化
ContextImpl appContext = createBaseContextForActivity(r);
// ...
Configuration config = new Configuration(mCompatConfiguration);
// ...
appContext.setOuterContext(activity);
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, window, r.configCallback,
        r.assistToken);

  ContextImpl是一个很重要的数据结构,它是Context的具体实现。ContextImpl通过Activity的attach方法和Activity建立关联,除此之外attach中Activity还完成Window的创建并建立自己和Window的关联,这样Window接收到的外部输入事件后就可以将事件传递给Activity(具体见笔者笔记:Android进阶知识(二十一):Window的创建过程)。

  1. 调用Activity的onCreate方法

  这个在流程中已经有所体现,其调用Instrumentation的callActivityOnCreate方法,进而调用Activity的onCreate,至此Activity的启动过程就完成了。
在这里插入图片描述

参考资料:《Android艺术开发探索》
     在Android 10.0中Activity的启动流程

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值